<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="utf-8"><title>Angular - 路由与导航</title><meta name="Description" content="Angular is a platform for building mobile and desktop web applications.
    Join the community of millions of developers who build compelling user interfaces with Angular."><base href="/"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="search" type="application/opensearchdescription+xml" href="assets/opensearch.xml"><link rel="icon" type="image/x-icon" href="assets/images/favicons/favicon.ico"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-32x32.png" sizes="32x32"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-194x194.png" sizes="194x194"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-16x16.png" sizes="16x16"><link rel="apple-touch-icon" sizes="144x144" href="assets/images/favicons/favicon-144x144.png"><link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/images/favicons/favicon-144x144.png"><link href="assets/fonts/Material_Icons.css" rel="stylesheet"><link href="assets/fonts/Droid_Sans_Mono.css" rel="stylesheet"><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"><link rel="manifest" href="pwa-manifest.json"><meta name="theme-color" content="#1976d2"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="translucent"><script async="" src="assets/js/analytics.js"></script><script>!function(e,a,n,t,s,c,g){e.GoogleAnalyticsObject=s,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(n),g=a.getElementsByTagName(n)[0],c.async=1,c.src="assets/js/analytics.js",~e.name.indexOf("NG_DEFER_BOOTSTRAP")||g.parentNode.insertBefore(c,g)}(window,document,"script",0,"ga")</script><script>window.onerror=function(){ga("send","exception",{exDescription:function(e,r,n,a,c){var l;e=e.replace(/^Error: /,""),l=c?c.stack.replace(/^Error: /,"").replace(e+"\n","").replace(/^ +/gm,"").replace(/^at /gm,"").replace(/(?: \(|@)http.+\/([^/)]+)\)?(?:\n|$)/gm,"@$1\n").replace(/ *\(eval code(:\d+:\d+)\)(?:\n|$)/gm,"@???$1\n"):r+":"+(n=n||"?")+":"+(a=a||"?");return(e+"\n"+l).substr(0,150)}.apply(null,arguments),exFatal:!0})}</script><link rel="stylesheet" href="styles.4adbe52ad34df01b5273.css"><style>.cdk-high-contrast-active .mat-toolbar{outline:solid 1px}.mat-toolbar-row,.mat-toolbar-single-row{display:flex;box-sizing:border-box;padding:0 16px;width:100%;flex-direction:row;align-items:center;white-space:nowrap}.mat-toolbar-multiple-rows{display:flex;box-sizing:border-box;flex-direction:column;width:100%}.mat-toolbar-multiple-rows{min-height:64px}.mat-toolbar-row,.mat-toolbar-single-row{height:64px}@media(max-width:599px){.mat-toolbar-multiple-rows{min-height:56px}.mat-toolbar-row,.mat-toolbar-single-row{height:56px}}</style><style>.mat-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;height:24px;width:24px}.mat-icon.mat-icon-inline{font-size:inherit;height:inherit;line-height:inherit;width:inherit}[dir=rtl] .mat-icon-rtl-mirror{transform:scale(-1,1)}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon{display:block}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button .mat-icon{margin:auto}</style><style>.mat-button .mat-button-focus-overlay,.mat-icon-button .mat-button-focus-overlay{opacity:0}.mat-button:hover .mat-button-focus-overlay,.mat-stroked-button:hover .mat-button-focus-overlay{opacity:.04}@media(hover:none){.mat-button:hover .mat-button-focus-overlay,.mat-stroked-button:hover .mat-button-focus-overlay{opacity:0}}.mat-button,.mat-flat-button,.mat-icon-button,.mat-stroked-button{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible}.mat-button::-moz-focus-inner,.mat-flat-button::-moz-focus-inner,.mat-icon-button::-moz-focus-inner,.mat-stroked-button::-moz-focus-inner{border:0}.mat-button[disabled],.mat-flat-button[disabled],.mat-icon-button[disabled],.mat-stroked-button[disabled]{cursor:default}.mat-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-button.cdk-program-focused .mat-button-focus-overlay,.mat-flat-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-flat-button.cdk-program-focused .mat-button-focus-overlay,.mat-icon-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-icon-button.cdk-program-focused .mat-button-focus-overlay,.mat-stroked-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-stroked-button.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-button::-moz-focus-inner,.mat-flat-button::-moz-focus-inner,.mat-icon-button::-moz-focus-inner,.mat-stroked-button::-moz-focus-inner{border:0}.mat-raised-button{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1)}.mat-raised-button::-moz-focus-inner{border:0}.mat-raised-button[disabled]{cursor:default}.mat-raised-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-raised-button.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-raised-button::-moz-focus-inner{border:0}._mat-animation-noopable.mat-raised-button{transition:none;animation:none}.mat-stroked-button{border:1px solid currentColor;padding:0 15px;line-height:34px}.mat-stroked-button .mat-button-focus-overlay,.mat-stroked-button .mat-button-ripple.mat-ripple{top:-1px;left:-1px;right:-1px;bottom:-1px}.mat-fab{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);min-width:0;border-radius:50%;width:56px;height:56px;padding:0;flex-shrink:0}.mat-fab::-moz-focus-inner{border:0}.mat-fab[disabled]{cursor:default}.mat-fab.cdk-keyboard-focused .mat-button-focus-overlay,.mat-fab.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-fab::-moz-focus-inner{border:0}._mat-animation-noopable.mat-fab{transition:none;animation:none}.mat-fab .mat-button-wrapper{padding:16px 0;display:inline-block;line-height:24px}.mat-mini-fab{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);min-width:0;border-radius:50%;width:40px;height:40px;padding:0;flex-shrink:0}.mat-mini-fab::-moz-focus-inner{border:0}.mat-mini-fab[disabled]{cursor:default}.mat-mini-fab.cdk-keyboard-focused .mat-button-focus-overlay,.mat-mini-fab.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-mini-fab::-moz-focus-inner{border:0}._mat-animation-noopable.mat-mini-fab{transition:none;animation:none}.mat-mini-fab .mat-button-wrapper{padding:8px 0;display:inline-block;line-height:24px}.mat-icon-button{padding:0;min-width:0;width:40px;height:40px;flex-shrink:0;line-height:40px;border-radius:50%}.mat-icon-button .mat-icon,.mat-icon-button i{line-height:24px}.mat-button-focus-overlay,.mat-button-ripple.mat-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-button-ripple.mat-ripple:not(:empty){transform:translateZ(0)}.mat-button-focus-overlay{opacity:0;transition:opacity .2s cubic-bezier(.35,0,.25,1),background-color .2s cubic-bezier(.35,0,.25,1)}._mat-animation-noopable .mat-button-focus-overlay{transition:none}.cdk-high-contrast-active .mat-button-focus-overlay{background-color:#fff}.cdk-high-contrast-black-on-white .mat-button-focus-overlay{background-color:#000}.mat-button-ripple-round{border-radius:50%;z-index:1}.mat-button .mat-button-wrapper>*,.mat-fab .mat-button-wrapper>*,.mat-flat-button .mat-button-wrapper>*,.mat-icon-button .mat-button-wrapper>*,.mat-mini-fab .mat-button-wrapper>*,.mat-raised-button .mat-button-wrapper>*,.mat-stroked-button .mat-button-wrapper>*{vertical-align:middle}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button{display:block;font-size:inherit;width:2.5em;height:2.5em}.cdk-high-contrast-active .mat-button,.cdk-high-contrast-active .mat-fab,.cdk-high-contrast-active .mat-flat-button,.cdk-high-contrast-active .mat-icon-button,.cdk-high-contrast-active .mat-mini-fab,.cdk-high-contrast-active .mat-raised-button{outline:solid 1px}</style><style>.mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-container-has-open{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:.4s;transition-timing-function:cubic-bezier(.25,.8,.25,1);transition-property:background-color,visibility}.cdk-high-contrast-active .mat-drawer-backdrop{opacity:.5}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:.4s;transition-timing-function:cubic-bezier(.25,.8,.25,1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%,0,0)}.cdk-high-contrast-active .mat-drawer,.cdk-high-contrast-active [dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}.cdk-high-contrast-active .mat-drawer.mat-drawer-end,.cdk-high-contrast-active [dir=rtl] .mat-drawer{border-left:solid 1px currentColor;border-right:none}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%,0,0)}[dir=rtl] .mat-drawer{transform:translate3d(100%,0,0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%,0,0)}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}</style><style>.nav-link.highlight[_ngcontent-ng-docs-c30]{color:#ff0}</style><style>.mat-progress-bar{display:block;height:4px;overflow:hidden;position:relative;transition:opacity 250ms linear;width:100%}._mat-animation-noopable.mat-progress-bar{transition:none;animation:none}.mat-progress-bar .mat-progress-bar-element,.mat-progress-bar .mat-progress-bar-fill::after{height:100%;position:absolute;width:100%}.mat-progress-bar .mat-progress-bar-background{width:calc(100% + 10px)}.cdk-high-contrast-active .mat-progress-bar .mat-progress-bar-background{display:none}.mat-progress-bar .mat-progress-bar-buffer{transform-origin:top left;transition:transform 250ms ease}.cdk-high-contrast-active .mat-progress-bar .mat-progress-bar-buffer{border-top:solid 5px;opacity:.5}.mat-progress-bar .mat-progress-bar-secondary{display:none}.mat-progress-bar .mat-progress-bar-fill{animation:none;transform-origin:top left;transition:transform 250ms ease}.cdk-high-contrast-active .mat-progress-bar .mat-progress-bar-fill{border-top:solid 4px}.mat-progress-bar .mat-progress-bar-fill::after{animation:none;content:"";display:inline-block;left:0}.mat-progress-bar[dir=rtl],[dir=rtl] .mat-progress-bar{transform:rotateY(180deg)}.mat-progress-bar[mode=query]{transform:rotateZ(180deg)}.mat-progress-bar[mode=query][dir=rtl],[dir=rtl] .mat-progress-bar[mode=query]{transform:rotateZ(180deg) rotateY(180deg)}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-fill,.mat-progress-bar[mode=query] .mat-progress-bar-fill{transition:none}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-primary,.mat-progress-bar[mode=query] .mat-progress-bar-primary{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-primary-indeterminate-translate 2s infinite linear;left:-145.166611%}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-primary.mat-progress-bar-fill::after,.mat-progress-bar[mode=query] .mat-progress-bar-primary.mat-progress-bar-fill::after{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-primary-indeterminate-scale 2s infinite linear}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-secondary,.mat-progress-bar[mode=query] .mat-progress-bar-secondary{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-secondary-indeterminate-translate 2s infinite linear;left:-54.888891%;display:block}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-secondary.mat-progress-bar-fill::after,.mat-progress-bar[mode=query] .mat-progress-bar-secondary.mat-progress-bar-fill::after{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-secondary-indeterminate-scale 2s infinite linear}.mat-progress-bar[mode=buffer] .mat-progress-bar-background{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-background-scroll 250ms infinite linear;display:block}.mat-progress-bar._mat-animation-noopable .mat-progress-bar-background,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-buffer,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-fill,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-fill::after,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-primary,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-primary.mat-progress-bar-fill::after,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-secondary,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-secondary.mat-progress-bar-fill::after{animation:none;transition:none}@keyframes mat-progress-bar-primary-indeterminate-translate{0%{transform:translateX(0)}20%{animation-timing-function:cubic-bezier(.5,0,.701732,.495819);transform:translateX(0)}59.15%{animation-timing-function:cubic-bezier(.302435,.381352,.55,.956352);transform:translateX(83.67142%)}100%{transform:translateX(200.611057%)}}@keyframes mat-progress-bar-primary-indeterminate-scale{0%{transform:scaleX(.08)}36.65%{animation-timing-function:cubic-bezier(.334731,.12482,.785844,1);transform:scaleX(.08)}69.15%{animation-timing-function:cubic-bezier(.06,.11,.6,1);transform:scaleX(.661479)}100%{transform:scaleX(.08)}}@keyframes mat-progress-bar-secondary-indeterminate-translate{0%{animation-timing-function:cubic-bezier(.15,0,.515058,.409685);transform:translateX(0)}25%{animation-timing-function:cubic-bezier(.31033,.284058,.8,.733712);transform:translateX(37.651913%)}48.35%{animation-timing-function:cubic-bezier(.4,.627035,.6,.902026);transform:translateX(84.386165%)}100%{transform:translateX(160.277782%)}}@keyframes mat-progress-bar-secondary-indeterminate-scale{0%{animation-timing-function:cubic-bezier(.15,0,.515058,.409685);transform:scaleX(.08)}19.15%{animation-timing-function:cubic-bezier(.31033,.284058,.8,.733712);transform:scaleX(.457104)}44.15%{animation-timing-function:cubic-bezier(.4,.627035,.6,.902026);transform:scaleX(.72796)}100%{transform:scaleX(.08)}}@keyframes mat-progress-bar-background-scroll{to{transform:translateX(-8px)}}</style><script charset="utf-8" src="toc-toc-module-es2015.f8531f591ee147aebcc6.js"></script><script charset="utf-8" src="default~code-code-example-module~code-code-tabs-module-es2015.9efcc76d2979a2e605e0.js"></script><script charset="utf-8" src="code-code-example-module-es2015.fa05e6f700453813d256.js"></script><script charset="utf-8" src="code-code-tabs-module-es2015.505e1e0a869946918011.js"></script><script charset="utf-8" src="live-example-live-example-module-es2015.d3b124043392e69f9e97.js"></script><script charset="utf-8" src="assets-js-prettify-js-es2015.ba856648f2dd2d930a9b.js"></script><style>.mat-card{transition:box-shadow 280ms cubic-bezier(.4,0,.2,1);display:block;position:relative;padding:16px;border-radius:4px}._mat-animation-noopable.mat-card{transition:none;animation:none}.mat-card .mat-divider-horizontal{position:absolute;left:0;width:100%}[dir=rtl] .mat-card .mat-divider-horizontal{left:auto;right:0}.mat-card .mat-divider-horizontal.mat-divider-inset{position:static;margin:0}[dir=rtl] .mat-card .mat-divider-horizontal.mat-divider-inset{margin-right:0}.cdk-high-contrast-active .mat-card{outline:solid 1px}.mat-card-actions,.mat-card-content,.mat-card-subtitle{display:block;margin-bottom:16px}.mat-card-title{display:block;margin-bottom:8px}.mat-card-actions{margin-left:-8px;margin-right:-8px;padding:8px 0}.mat-card-actions-align-end{display:flex;justify-content:flex-end}.mat-card-image{width:calc(100% + 32px);margin:0 -16px 16px -16px}.mat-card-footer{display:block;margin:0 -16px -16px -16px}.mat-card-actions .mat-button,.mat-card-actions .mat-raised-button,.mat-card-actions .mat-stroked-button{margin:0 8px}.mat-card-header{display:flex;flex-direction:row}.mat-card-header .mat-card-title{margin-bottom:12px}.mat-card-header-text{margin:0 16px}.mat-card-avatar{height:40px;width:40px;border-radius:50%;flex-shrink:0;object-fit:cover}.mat-card-title-group{display:flex;justify-content:space-between}.mat-card-sm-image{width:80px;height:80px}.mat-card-md-image{width:112px;height:112px}.mat-card-lg-image{width:152px;height:152px}.mat-card-xl-image{width:240px;height:240px;margin:-8px}.mat-card-title-group>.mat-card-xl-image{margin:-8px 0 8px}@media(max-width:599px){.mat-card-title-group{margin:0}.mat-card-xl-image{margin-left:0;margin-right:0}}.mat-card-content>:first-child,.mat-card>:first-child{margin-top:0}.mat-card-content>:last-child:not(.mat-card-footer),.mat-card>:last-child:not(.mat-card-footer){margin-bottom:0}.mat-card-image:first-child{margin-top:-16px;border-top-left-radius:inherit;border-top-right-radius:inherit}.mat-card>.mat-card-actions:last-child{margin-bottom:-8px;padding-bottom:0}.mat-card-actions .mat-button:first-child,.mat-card-actions .mat-raised-button:first-child,.mat-card-actions .mat-stroked-button:first-child{margin-left:0;margin-right:0}.mat-card-subtitle:not(:first-child),.mat-card-title:not(:first-child){margin-top:-4px}.mat-card-header .mat-card-subtitle:not(:first-child){margin-top:-8px}.mat-card>.mat-card-xl-image:first-child{margin-top:-8px}.mat-card>.mat-card-xl-image:last-child{margin-bottom:-8px}</style><style>.mat-tab-group{display:flex;flex-direction:column}.mat-tab-group.mat-tab-group-inverted-header{flex-direction:column-reverse}.mat-tab-label{height:48px;padding:0 24px;cursor:pointer;box-sizing:border-box;opacity:.6;min-width:160px;text-align:center;display:inline-flex;justify-content:center;align-items:center;white-space:nowrap;position:relative}.mat-tab-label:focus{outline:0}.mat-tab-label:focus:not(.mat-tab-disabled){opacity:1}.cdk-high-contrast-active .mat-tab-label:focus{outline:dotted 2px}.mat-tab-label.mat-tab-disabled{cursor:default}.cdk-high-contrast-active .mat-tab-label.mat-tab-disabled{opacity:.5}.mat-tab-label .mat-tab-label-content{display:inline-flex;justify-content:center;align-items:center;white-space:nowrap}.cdk-high-contrast-active .mat-tab-label{opacity:1}@media(max-width:599px){.mat-tab-label{padding:0 12px}}@media(max-width:959px){.mat-tab-label{padding:0 12px}}.mat-tab-group[mat-stretch-tabs]>.mat-tab-header .mat-tab-label{flex-basis:0;flex-grow:1}.mat-tab-body-wrapper{position:relative;overflow:hidden;display:flex;transition:height .5s cubic-bezier(.35,0,.25,1)}._mat-animation-noopable.mat-tab-body-wrapper{transition:none;animation:none}.mat-tab-body{top:0;left:0;right:0;bottom:0;position:absolute;display:block;overflow:hidden;flex-basis:100%}.mat-tab-body.mat-tab-body-active{position:relative;overflow-x:hidden;overflow-y:auto;z-index:1;flex-grow:1}.mat-tab-group.mat-tab-group-dynamic-height .mat-tab-body.mat-tab-body-active{overflow-y:hidden}</style><style>.mat-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0}.mat-tab-header-pagination{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2;-webkit-tap-highlight-color:transparent;touch-action:none}.mat-tab-header-pagination-controls-enabled .mat-tab-header-pagination{display:flex}.mat-tab-header-pagination-before,.mat-tab-header-rtl .mat-tab-header-pagination-after{padding-left:4px}.mat-tab-header-pagination-before .mat-tab-header-pagination-chevron,.mat-tab-header-rtl .mat-tab-header-pagination-after .mat-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-tab-header-pagination-after,.mat-tab-header-rtl .mat-tab-header-pagination-before{padding-right:4px}.mat-tab-header-pagination-after .mat-tab-header-pagination-chevron,.mat-tab-header-rtl .mat-tab-header-pagination-before .mat-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;content:"";height:8px;width:8px}.mat-tab-header-pagination-disabled{box-shadow:none;cursor:default}.mat-tab-list{flex-grow:1;position:relative;transition:transform .5s cubic-bezier(.35,0,.25,1)}.mat-ink-bar{position:absolute;bottom:0;height:2px;transition:.5s cubic-bezier(.35,0,.25,1)}._mat-animation-noopable.mat-ink-bar{transition:none;animation:none}.mat-tab-group-inverted-header .mat-ink-bar{bottom:auto;top:0}.cdk-high-contrast-active .mat-ink-bar{outline:solid 2px;height:0}.mat-tab-labels{display:flex}[mat-align-tabs=center] .mat-tab-labels{justify-content:center}[mat-align-tabs=end] .mat-tab-labels{justify-content:flex-end}.mat-tab-label-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}._mat-animation-noopable.mat-tab-list{transition:none;animation:none}.mat-tab-label{height:48px;padding:0 24px;cursor:pointer;box-sizing:border-box;opacity:.6;min-width:160px;text-align:center;display:inline-flex;justify-content:center;align-items:center;white-space:nowrap;position:relative}.mat-tab-label:focus{outline:0}.mat-tab-label:focus:not(.mat-tab-disabled){opacity:1}.cdk-high-contrast-active .mat-tab-label:focus{outline:dotted 2px}.mat-tab-label.mat-tab-disabled{cursor:default}.cdk-high-contrast-active .mat-tab-label.mat-tab-disabled{opacity:.5}.mat-tab-label .mat-tab-label-content{display:inline-flex;justify-content:center;align-items:center;white-space:nowrap}.cdk-high-contrast-active .mat-tab-label{opacity:1}@media(max-width:599px){.mat-tab-label{min-width:72px}}</style><style>.mat-tab-body-content{height:100%;overflow:auto}.mat-tab-group-dynamic-height .mat-tab-body-content{overflow:hidden}</style></head><body><aio-shell ng-version="9.0.0-rc.11" class="aio-notification-hide folder-guide mode-stable page-guide-router sidenav-open view-SideNav"><div id="top-of-page"></div><mat-toolbar color="primary" class="mat-toolbar app-toolbar no-print mat-primary mat-toolbar-multiple-rows"><mat-toolbar-row class="mat-toolbar-row notification-container"><aio-notification notificationid="survey-february-2019" expirationdate="2019-03-01" class="ng-tns-c22-0 ng-trigger ng-trigger-hideAnimation" style="height:0"><span class="content ng-tns-c22-0"><a href="http://bit.ly/angular-survey-2019" target="_blank" class="ng-tns-c22-0"><mat-icon role="img" svgicon="insert_comment" aria-label="Announcement" class="mat-icon notranslate icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></mat-icon><span class="message"><b>填写这份《一分钟调查》</b>，帮我们（开发组）做得更好！</span><span class="action-button">去填写</span></a></span><button mat-icon-button="" aria-label="Close" class="close-button ng-tns-c22-0 mat-icon-button mat-button-base"><span class="mat-button-wrapper"><mat-icon role="img" svgicon="close" aria-label="Dismiss notification" class="mat-icon notranslate mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></mat-icon></span><div matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round"></div><div class="mat-button-focus-overlay"></div></button></aio-notification></mat-toolbar-row><mat-toolbar-row class="mat-toolbar-row"><button mat-button="" title="Docs menu" class="hamburger mat-button mat-button-base"><span class="mat-button-wrapper"><mat-icon role="img" svgicon="menu" class="mat-icon notranslate mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg></mat-icon></span><div matripple="" class="mat-ripple mat-button-ripple"></div><div class="mat-button-focus-overlay"></div></button><a href="/" class="nav-link home"><img src="assets/images/logos/angular/logo-nav@2x.png" width="150" height="40" title="Home" alt="Home" class="ng-star-inserted"></a><aio-top-menu _nghost-ng-docs-c30="" class="ng-star-inserted"><ul _ngcontent-ng-docs-c30="" role="navigation"><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="features" title="特性" target="_self"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">特性</span></a></li><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="docs" title="文档" target="_self"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">文档</span></a></li><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="resources" title="资源" target="_self"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">资源</span></a></li><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="events" title="会议" target="_self"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">会议</span></a></li><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="https://blog.wangke.io/" title="译者汪志成的博客，包括翻译文章和原创文章" target="_blank"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">译者博客</span></a></li><li _ngcontent-ng-docs-c30="" class="ng-star-inserted"><a _ngcontent-ng-docs-c30="" class="nav-link" href="translations/cn/home" title="关于中文版" target="_self"><span _ngcontent-ng-docs-c30="" class="nav-link-inner">关于中文版</span></a></li></ul></aio-top-menu><aio-search-box class="search-container"><input type="search" aria-label="search" placeholder="搜索"></aio-search-box><div class="toolbar-external-icons-container"><a href="https://twitter.com/angular" title="Twitter" aria-label="Angular on twitter"><mat-icon role="img" svgicon="logos:twitter" class="mat-icon notranslate mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 50 59" xmlns="http://www.w3.org/2000/svg"><path d="M50,9.3c-1.8,0.8-3.8,1.4-5.9,1.6c2.1-1.3,3.7-3.3,4.5-5.7c-2,1.2-4.2,2-6.5,2.5c-1.9-2-4.5-3.2-7.5-3.2c-5.7,0-10.3,4.6-10.3,10.3c0,0.8,0.1,1.6,0.3,2.3C16.1,16.7,8.5,12.6,3.5,6.4c-0.9,1.5-1.4,3.3-1.4,5.2c0,3.6,1.8,6.7,4.6,8.5C5,20,3.4,19.6,2,18.8c0,0,0,0.1,0,0.1c0,5,3.5,9.1,8.2,10.1c-0.9,0.2-1.8,0.4-2.7,0.4c-0.7,0-1.3-0.1-1.9-0.2c1.3,4.1,5.1,7,9.6,7.1c-3.5,2.8-7.9,4.4-12.7,4.4c-0.8,0-1.6,0-2.4-0.1c4.5,2.9,9.9,4.6,15.7,4.6c18.9,0,29.2-15.6,29.2-29.2c0-0.4,0-0.9,0-1.3C46.9,13.2,48.6,11.4,50,9.3z"></path></svg></mat-icon></a><a href="https://github.com/angular/angular" title="GitHub" aria-label="Angular on github"><mat-icon role="img" svgicon="logos:github" class="mat-icon notranslate mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 51.8 50.4" xmlns="http://www.w3.org/2000/svg"><path d="M25.9,0.2C11.8,0.2,0.3,11.7,0.3,25.8c0,11.3,7.3,20.9,17.5,24.3c1.3,0.2,1.7-0.6,1.7-1.2c0-0.6,0-2.6,0-4.8c-7.1,1.5-8.6-3-8.6-3c-1.2-3-2.8-3.7-2.8-3.7c-2.3-1.6,0.2-1.6,0.2-1.6c2.6,0.2,3.9,2.6,3.9,2.6c2.3,3.9,6,2.8,7.5,2.1c0.2-1.7,0.9-2.8,1.6-3.4c-5.7-0.6-11.7-2.8-11.7-12.7c0-2.8,1-5.1,2.6-6.9c-0.3-0.7-1.1-3.3,0.3-6.8c0,0,2.1-0.7,7,2.6c2-0.6,4.2-0.9,6.4-0.9c2.2,0,4.4,0.3,6.4,0.9c4.9-3.3,7-2.6,7-2.6c1.4,3.5,0.5,6.1,0.3,6.8c1.6,1.8,2.6,4.1,2.6,6.9c0,9.8-6,12-11.7,12.6c0.9,0.8,1.7,2.4,1.7,4.7c0,3.4,0,6.2,0,7c0,0.7,0.5,1.5,1.8,1.2c10.2-3.4,17.5-13,17.5-24.3C51.5,11.7,40.1,0.2,25.9,0.2z"></path></svg></mat-icon></a></div></mat-toolbar-row></mat-toolbar><mat-sidenav-container role="main" class="mat-drawer-container mat-sidenav-container sidenav-container mat-drawer-transition has-floating-toc"><div class="mat-drawer-backdrop ng-star-inserted"></div><div class="cdk-visually-hidden cdk-focus-trap-anchor" aria-hidden="true"></div><mat-sidenav tabindex="-1" class="mat-drawer mat-sidenav sidenav ng-tns-c18-1 ng-trigger ng-trigger-transform mat-drawer-side ng-star-inserted mat-drawer-opened" style="transform:none;visibility:visible"><div class="mat-drawer-inner-container ng-tns-c18-1"><aio-nav-menu class="ng-tns-c18-1"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="docs" title="Angular 文档简介" target="_self"><span>简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="通过构建第一个 Angular 应用来学习基础知识" aria-pressed="false"><span>快速上手</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="start" title="介绍 Angular 的组件模型、模板语法和组件通讯" target="_self"><span>你的第一个应用</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="start/routing" title="介绍如何使用浏览器的 URL 在组件之间进行路由" target="_self"><span>路由</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="start/data" title="介绍服务以及如何访问外部数据" target="_self"><span>管理数据</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="start/forms" title="学习如何使用表单从用户那里获取并管理数据" target="_self"><span>表单</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="start/deployment" title="通过你的应用放到 Firebase 或自己的服务器上来把它分享给外界" target="_self"><span>部署</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="guide/setup-local" title="使用 Angular CLI 搭建本地开发环境简介" target="_self"><span>搭建环境</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 expanded selected ng-star-inserted" title="Angular 的基本原理" aria-pressed="true"><span>基本原理</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 expanded selected"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="介绍 Angular 应用中的一些基本概念。" aria-pressed="false"><span>Angular 的基本概念</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture" title="Angular 应用中的基本构造块。" target="_self"><span>基本概念简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-modules" title="关于 Angular 模块（NgModules）。" target="_self"><span>模块简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-components" title="关于组件、模板和视图。" target="_self"><span>组件简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-services" title="关于服务与依赖注入。" target="_self"><span>服务与 DI 简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-next-steps" title="超越基础阶段。" target="_self"><span>后续步骤</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="英雄指南是这里大量 Angular 范例的基础" aria-pressed="false"><span>英雄指南</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial" title="《英雄指南》教程简介" target="_self"><span>简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt0" title="创建应用的外壳" target="_self"><span>应用的“外壳”</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt1" title="第一部分：构建一个简单的英雄编辑器" target="_self"><span>1. 英雄编辑器</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt2" title="第二部分：构建一个主从结构的页面，用于展现英雄列表。" target="_self"><span>2. 显示英雄列表</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt3" title="第三部分：把主从结构的视图重构成几个独立的组件。" target="_self"><span>3. 创建特性组件</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt4" title="第四部分：创建一个可复用的服务来管理英雄数据。" target="_self"><span>4. 添加服务</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt5" title="第五部分：添加 Angular 路由器，并且学习在视图之间导航。" target="_self"><span>5. 添加应用内导航</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt6" title="第六部分：通过 HTTP 来获取并保存英雄数据。" target="_self"><span>6. 从服务器获取数据</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="通过数据绑定构建动态视图" aria-pressed="false"><span>组件与模板</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/displaying-data" title="属性绑定可以帮助应用把数据显示在界面上" target="_self"><span>显示数据</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/template-syntax" title="学习如何写模板，以便借助数据绑定机制显示数据并响应事件。" target="_self"><span>模板语法</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/user-input" title="用户输入会触发 DOM 事件。Angular 会通过事件绑定来监听那些事件，并把修改后的值传回应用的组件和模型中。" target="_self"><span>用户输入</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/lifecycle-hooks" title="Angular 调用指令和组件的生命周期钩子函数，包括它的创建、变更和销毁时。" target="_self"><span>生命周期钩子</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/component-interaction" title="在不同的指令和组件之间共享信息" target="_self"><span>组件交互</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/component-styles" title="添加专属于某个组件的样式" target="_self"><span>组件样式</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dynamic-component-loader" title="动态加载组件" target="_self"><span>动态组件</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/elements" title="把组件转换成自定义元素" target="_self"><span>Angular 元素</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/attribute-directives" title="属性型指令把行为添加到现有元素上。" target="_self"><span>属性型指令</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/structural-directives" title="结构型指令可以操纵页面的布局" target="_self"><span>结构型指令</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/pipes" title="管道可以在模板中转换显示的内容。" target="_self"><span>管道</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="Angular 的表单" aria-pressed="false"><span>表单</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/forms-overview" title="表单可以创建集中、高效、引人注目的输入体验。Angular 表单可以协调一组数据绑定控件，跟踪变更，验证输入，并表达错误信息。" target="_self"><span>简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/reactive-forms" title="使用 FormBuilder、表单组和表单数组创建响应式表单。" target="_self"><span>响应式表单</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/forms" title="使用指令和 Angular 模板语法创建模板驱动表单。" target="_self"><span>模板驱动表单</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/form-validation" title="验证用户的表单输入" target="_self"><span>表单验证</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dynamic-form" title="使用 FormGroup 渲染动态表单。" target="_self"><span>动态表单</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="Observable 与 RxJS" aria-pressed="false"><span>Observable 与 RxJS</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/observables" title="" target="_self"><span>可观察对象(Observable)</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/rx-library" title="" target="_self"><span>RxJS 库</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/observables-in-angular" title="" target="_self"><span>Angular 中的可观察对象</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/practical-observable-usage" title="" target="_self"><span>用法实战</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/comparing-observables" title="" target="_self"><span>与其它技术的比较</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="Angular 中的模块" aria-pressed="false"><span>NgModules</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodules" title="使用 NgModule 让你的应用更高效" target="_self"><span>NgModule 简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-vs-jsmodule" title="JavaScript 模块和 NgModule 之间的差异" target="_self"><span>JS 模块 vs NgModule</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/bootstrapping" title="告诉 Angular 如何在根 &quot;AppModule&quot; 中构造和引导应用。" target="_self"><span>应用的根模块</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/frequent-ngmodules" title="介绍最常用的 NgModule" target="_self"><span>常用模块</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/module-types" title="介绍特性模块的几种类型" target="_self"><span>特性模块的分类</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/entry-components" title="关于 Angular 中入口组件的一切" target="_self"><span>入口组件</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/feature-modules" title="创建特性模块，以组织你的代码" target="_self"><span>特性模块</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/providers" title="服务提供者与 NgModule" target="_self"><span>服务提供者</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/singleton-services" title="创建单例服务" target="_self"><span>单例服务</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/lazy-loading-ngmodules" title="惰性加载模块，以提高应用的性能" target="_self"><span>惰性加载的特性模块</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/sharing-ngmodules" title="共享 NgModule 让你的应用现代化。" target="_self"><span>共享 NgModule</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-api" title="理解 NgModule 的那些细节。" target="_self"><span>NgModule API</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-faq" title="回答关于 NgModules 的常见问题。" target="_self"><span>NgModule 常见问题</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="依赖注入：创建并注入各种服务。" aria-pressed="false"><span>依赖注入</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection" title="Angular 的依赖注入系统能够为 Angular 创建的类创建并交付它们所依赖的服务。" target="_self"><span>Angular 依赖注入</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/hierarchical-dependency-injection" title="与组件树平行的注入器树，并支持嵌套的依赖。" target="_self"><span>多级注入器</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-providers" title="各种提供者类型的更多知识。" target="_self"><span>DI 提供者</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-in-action" title="依赖注入的使用技巧" target="_self"><span>DI 实战</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-navtree" title="使用注入器树来查找父组件。" target="_self"><span>浏览组件树</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/http" title="通过 HTTP 协议与远程服务器对话。" target="_self"><span>HttpClient</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 expanded selected ng-star-inserted" style="position:relative" href="guide/router" title="揭示如何通过 Angular 路由进行基本的屏幕导航。" target="_self"><span>路由与导航</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="Angular 动画系统指南" aria-pressed="false"><span>动画</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/animations" title="Angular 动画的基础技术。" target="_self"><span>简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/transition-and-triggers" title="转场与触发器的高级技术。" target="_self"><span>转场与触发器</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/complex-animation-sequences" title="复杂的 Angular 动画序列。" target="_self"><span>复杂序列</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/reusable-animations" title="创建可复用的动画。" target="_self"><span>可复用动画</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/route-animations" title="为路由提供转场动画。" target="_self"><span>路由转场动画</span></a></div></aio-nav-item></div></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="把 Angular 用到你的实际工作中的一些技巧" aria-pressed="false"><span>其它技术</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/security" title="Angular 应用开发中的安全技术。" target="_self"><span>安全</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/i18n" title="把应用模板中的文本翻译成多种语言。" target="_self"><span>国际化（i18n）</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/accessibility" title="设计能被所有用户访问的应用" target="_self"><span>无障碍（a11y）</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="Angular Service Worker: 控制应用资源的缓存。" aria-pressed="false"><span>Service Worker 与 PWA</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-intro" title="Angular 对 Service Worker 的实现提升了慢速或不稳定的网络连接下的用户体验。" target="_self"><span>简介</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-getting-started" title="在 CLI 项目中启用 Service Worker，并在浏览器中查看效果。" target="_self"><span>快速上手</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/app-shell" title="在 CLI 项目中启用应用外壳。" target="_self"><span>应用外壳</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-communications" title="那些能让你和 Angular 的 Service Worker 通讯的服务类。" target="_self"><span>与 Service Worker 通讯</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-devops" title="使用 Service Worker 运行应用、管理应用更新、调试以及杀掉正在运行的应用。" target="_self"><span>生产环境下的 Service Worker</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-config" title="配置 Service Worker 的缓存行为。" target="_self"><span>Service Worker 配置</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/universal" title="使用 Angular Universal 在服务端渲染 HTML。" target="_self"><span>服务端渲染</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="把 AngularJS 应用增量式的升级到 Angular。" aria-pressed="false"><span>从 AngularJS 升级</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/upgrade" title="把 AngularJS 应用增量式的升级到 Angular。" target="_self"><span>升级步骤</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/upgrade-performance" title="用更灵活的方式把 AngularJS 升级到 Angular。" target="_self"><span>更关注性能的升级方式</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ajs-quick-reference" title="学习如何把 AngularJS 的概念映射到 Angular 中。" target="_self"><span>AngularJS 与 Angular 的概念对照</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="使用共享库扩展 Angular" aria-pressed="false"><span>开发 Angular 库</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/libraries" title="理解何时以及如何使用和创建库。" target="_self"><span>库概览</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/using-libraries" title="把已发布的库集成进你的应用中。" target="_self"><span>使用已发布的库</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/creating-libraries" title="通过创建、发布和使用你自己的库来扩展 Angular。" target="_self"><span>创建库</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="理解原理图" aria-pressed="false"><span>原理图（Schematic）</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/schematics" title="理解 Angular 如何使用原理图。" target="_self"><span>原理图概览</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/schematics-authoring" title="理解原理图的结构。" target="_self"><span>制作原理图</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/schematics-for-libraries" title="使用原理图来把你的库集成进 Angular CLI 中。" target="_self"><span>库的原理图</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/cli-builder" title="使用构建器定制 Angular CLI。" target="_self"><span>CLI 构建器</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/web-worker" title="在 Angular CLI 中使用 Web Worker。" target="_self"><span>Web Worker</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="关于构建、测试和部署的信息" aria-pressed="false"><span>开发工作流</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="理解 AOT 预先编译器。" aria-pressed="false"><span>AOT 预先编译器</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/aot-compiler" title="学习为何以及如何使用预先编译器。" target="_self"><span>预先编译</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/angular-compiler-options" title="配置 AOT 编译。" target="_self"><span>Angular 编译器选项</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/aot-metadata-errors" title="解决 AOT 编译错误。" target="_self"><span>AOT 元数据错误</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/template-typecheck" title="Angular 中的模板类型检查。" target="_self"><span>模板类型检查</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/build" title="构建应用及为应用启动开发服务器。" target="_self"><span>构建与运行</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/bazel" title="如何配置你的环境，以利用 Bazel 进行构建和测试。" target="_self"><span>使用 Bazel 进行构建</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/testing" title="测试 Angular 应用的技巧与实践。" target="_self"><span>测试</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/deployment" title="了解如何部署 Angular 应用。" target="_self"><span>发布</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-2 collapsed ng-star-inserted" title="与开发环境和工具集成起来" aria-pressed="false"><span>开发工具集成</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/language-service" title="使用 Angular 语言服务加速开发。" target="_self"><span>语言服务</span></a></div></aio-nav-item></div></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="工作空间与项目的结构，及其配置文件。" aria-pressed="false"><span>配置</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/file-structure" title="Angular 工作区在文件系统中是怎样的。" target="_self"><span>项目文件结构</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/workspace-config" title="&quot;angular.json&quot; 包含供 CLI 命令使用的工作区和项目默认配置。" target="_self"><span>工作区配置</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/npm-packages" title="开发期间和运行期间所需的 npm 包的说明。" target="_self"><span>npm 包</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/typescript-configuration" title="给 Angular 开发者的 TypeScript 配置。" target="_self"><span>TypeScript 配置</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/browser-support" title="浏览器支持与腻子脚本指南。" target="_self"><span>浏览器支持</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="Angular 的版本发布实践、更新与升级。" aria-pressed="false"><span>发布信息</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/updating" title="如何把 Angular 应用和库升级到最新版本。" target="_self"><span>保持最新</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/releases" title="Angular 的版本、发布、支持、弃用策略及实践。" target="_self"><span>发布实践</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/updating-to-version-9" title="支持把你的应用从 8 升级到 9。" target="_self"><span>升级到第 9 版</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/deprecations" title="弃用的 Angular API 和特性汇总。" target="_self"><span>弃用清单</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/ivy" title="关于 Angular Ivy 的编译与渲染管道。" target="_self"><span>Angular Ivy</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="Angular 语法、编码、术语汇总。" aria-pressed="false"><span>快捷手册</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/cheatsheet" title="关于 Angular 常用编码技术的快速指南。" target="_self"><span>速查表</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/styleguide" title="写出 Angular 风格的程序" target="_self"><span>风格指南</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/glossary" title="Angular 中最重要的词汇的简要定义。" target="_self"><span>词汇表</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button type="button" class="vertical-menu-item heading level-1 collapsed ng-star-inserted" title="Angular CLI 命令参考手册。" aria-pressed="false"><span>CLI 命令</span><mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli" title="CLI 工具介绍、命令、语法" target="_self"><span>概览</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/usage-analytics-gathering" title="管理员如何从用户那里收集使用情况分析。" target="_self"><span>使用情况分析</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/add" title="ng add." target="_self"><span>ng add</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/analytics" title="ng analytics." target="_self"><span>ng analytics</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/build" title="ng build." target="_self"><span>ng build</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/config" title="ng config." target="_self"><span>ng config</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/deploy" title="ng deploy." target="_self"><span>ng deploy</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/doc" title="ng doc." target="_self"><span>ng doc</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/e2e" title="ng e2e." target="_self"><span>ng e2e</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/generate" title="ng generate." target="_self"><span>ng generate</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/help" title="ng help." target="_self"><span>ng help</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/lint" title="ng lint." target="_self"><span>ng lint</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/new" title="ng new." target="_self"><span>ng new</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/run" title="ng run." target="_self"><span>ng run</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/serve" title="ng serve." target="_self"><span>ng serve</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/test" title="ng test." target="_self"><span>ng test</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/update" title="ng update." target="_self"><span>ng update</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/version" title="ng version." target="_self"><span>ng version</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/xi18n" title="ng xi18n." target="_self"><span>ng xi18n</span></a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="api" title="关于 Angular 中类和值的详细信息。" target="_self"><span>API 参考手册</span></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><div class="mat-divider ng-star-inserted" style="margin:4px 20px;border-top:1px solid #d3d3d3"></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://github.com/ng-docs/ng-docs.github.io/issues" title="github 上的中文互助问答区" target="_blank"><span>互助问答</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://material.angular.cn" title="Angular Material 组件库的中文文档" target="_blank"><span>官方 Material 组件库</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://ng.ant.design/" title="Ant Design 的 Angular 实现，服务于企业级后台产品。" target="_blank"><span>ng-zorro 组件库</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://devui.design/" title="“华为云” 开源的企业级组件库，核心设计思想是：致简、沉浸、灵活" target="_blank"><span>华为 DevUI 组件库</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://ng.mobile.ant.design/" title="Ant Design Mobile 的 Angular 实现，服务于无线产品。" target="_blank"><span>ng-zorro mobile 组件库</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://flutter.cn/" title="Flutter 中文文档站" target="_blank"><span>友站：Flutter 中文</span><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item></aio-nav-menu><div class="doc-version ng-tns-c18-1"><aio-select><div class="form-select-menu"><button class="form-select-button"><span><strong></strong></span><span>stable (v9.0.0)</span></button></div></aio-select></div></div></mat-sidenav><div class="cdk-visually-hidden cdk-focus-trap-anchor" aria-hidden="true"></div><mat-sidenav-content cdkscrollable="" class="mat-drawer-content mat-sidenav-content ng-star-inserted" style="margin-left:261px"><main role="main" class="sidenav-content" id="guide-router"><aio-mode-banner></aio-mode-banner><aio-doc-viewer class=""><div style="opacity:1"><div class="github-links"><a href="https://github.com/angular/angular-cn/edit/aio/aio/content/guide/router.md?message=docs%3A%20请简述你的修改..." aria-label="提供编辑建议" title="提供编辑建议"><i class="material-icons" aria-hidden="true" role="img">mode_edit</i></a></div><div class="content"><h1 id="routing-and-navigation" translation-result="on">路由与导航<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#routing-and-navigation"><i class="material-icons">link</i></a></h1><aio-toc class="embedded" ng-version="9.0.0-rc.11"><div class="toc-inner no-print collapsed ng-star-inserted"><button type="button" title="Expand/collapse contents" aria-label="Expand/collapse contents" class="toc-heading embedded secondary ng-star-inserted" aria-pressed="false">目录<mat-icon role="img" svgicon="keyboard_arrow_right" class="mat-icon notranslate rotating-icon collapsed mat-icon-no-color" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><ul class="toc-list embedded"><li class="h2 ng-star-inserted" title="概览"><a href="guide/router#overview">概览</a></li><li class="h2 ng-star-inserted" title="基础知识"><a href="guide/router#the-basics">基础知识</a></li><li class="h3 ng-star-inserted" title="<base href> 元素"><a href="guide/router#base-href"><em>&lt;base href&gt;</em> 元素</a></li><li class="h3 secondary ng-star-inserted" title="从路由库中导入"><a href="guide/router#router-imports">从路由库中导入</a></li><li class="h3 secondary ng-star-inserted" title="配置"><a href="guide/router#configuration">配置</a></li><li class="h3 secondary ng-star-inserted" title="路由出口"><a href="guide/router#router-outlet">路由出口</a></li><li class="h3 secondary ng-star-inserted" title="路由器链接"><a href="guide/router#router-links">路由器链接</a></li><li class="h3 secondary ng-star-inserted" title="路由链接的激活状态"><a href="guide/router#active-router-links">路由链接的激活状态</a></li><li class="h3 secondary ng-star-inserted" title="路由器状态"><a href="guide/router#router-state">路由器状态</a></li><li class="h3 secondary ng-star-inserted" title="激活的路由"><a href="guide/router#activated-route">激活的路由</a></li><li class="h3 secondary ng-star-inserted" title="路由事件"><a href="guide/router#router-events">路由事件</a></li><li class="h3 secondary ng-star-inserted" title="总结一下"><a href="guide/router#summary">总结一下</a></li><li class="h2 secondary ng-star-inserted" title="范例应用"><a href="guide/router#the-sample-application">范例应用</a></li><li class="h3 secondary ng-star-inserted" title="范例程序的动图"><a href="guide/router#the-sample-application-in-action">范例程序的动图</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 1：起步"><a href="guide/router#milestone-1-getting-started">里程碑 1：起步</a></li><li class="h3 secondary ng-star-inserted" title="定义路由"><a href="guide/router#define-routes">定义路由</a></li><li class="h3 secondary ng-star-inserted" title="注册路由器与路由定义"><a href="guide/router#register-router-and-routes">注册路由器与路由定义</a></li><li class="h3 secondary ng-star-inserted" title="添加路由出口"><a href="guide/router#add-the-router-outlet">添加路由出口</a></li><li class="h3 secondary ng-star-inserted" title="定义通配符路由"><a href="guide/router#define-a-wildcard-route">定义通配符路由</a></li><li class="h3 secondary ng-star-inserted" title="设置跳转"><a href="guide/router#set-up-redirects">设置跳转</a></li><li class="h3 secondary ng-star-inserted" title="“起步阶段”总结"><a href="guide/router#basics-wrap-up">“起步阶段”总结</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 2：路由模块"><a href="guide/router#milestone-2-routing-module">里程碑 2：<strong>路由模块</strong></a></li><li class="h3 secondary ng-star-inserted" title="把路由集成到应用中"><a href="guide/router#integrate-routing-with-your-app">把路由集成到应用中</a></li><li class="h3 secondary ng-star-inserted" title="将路由配置重构为路由模块"><a href="guide/router#refactor-the-routing-configuration-into-a-routing-module">将路由配置重构为<em>路由模块</em></a></li><li class="h3 secondary ng-star-inserted" title="你需要路由模块吗？"><a href="guide/router#do-you-need-a-routing-module">你需要<strong>路由模块</strong>吗？</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 3: 英雄特征区"><a href="guide/router#milestone-3-heroes-feature">里程碑 3: 英雄特征区</a></li><li class="h3 secondary ng-star-inserted" title="添加英雄管理功能"><a href="guide/router#add-heroes-functionality">添加英雄管理功能</a></li><li class="h3 secondary ng-star-inserted" title="导入模块的顺序很重要"><a href="guide/router#module-import-order-matters">导入模块的顺序很重要</a></li><li class="h3 secondary ng-star-inserted" title="路由参数"><a href="guide/router#route-parameters">路由参数</a></li><li class="h3 secondary ng-star-inserted" title="Activated Route 实战"><a href="guide/router#activated-route-in-action"><em>Activated Route</em> 实战</a></li><li class="h3 secondary ng-star-inserted" title="导航回列表组件"><a href="guide/router#navigating-back-to-the-list-component">导航回列表组件</a></li><li class="h3 secondary ng-star-inserted" title="ActivatedRoute 服务中的路由参数"><a href="guide/router#route-parameters-in-the-activatedroute-service"><em>ActivatedRoute</em> 服务中的路由参数</a></li><li class="h3 secondary ng-star-inserted" title="添加路由动画"><a href="guide/router#adding-routable-animations">添加路由动画</a></li><li class="h3 secondary ng-star-inserted" title="里程碑 3 的总结"><a href="guide/router#milestone-3-wrap-up">里程碑 3 的总结</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 4：危机中心"><a href="guide/router#milestone-4-crisis-center-feature">里程碑 4：危机中心</a></li><li class="h3 secondary ng-star-inserted" title="带有子路由的危机中心"><a href="guide/router#a-crisis-center-with-child-routes">带有子路由的危机中心</a></li><li class="h3 secondary ng-star-inserted" title="子路由组件"><a href="guide/router#child-routing-component">子路由组件</a></li><li class="h3 secondary ng-star-inserted" title="子路由配置"><a href="guide/router#child-route-configuration">子路由配置</a></li><li class="h3 secondary ng-star-inserted" title="把危机中心模块导入到 AppModule 的路由中"><a href="guide/router#import-crisis-center-module-into-the-appmodule-routes">把危机中心模块导入到 <code>AppModule</code> 的路由中</a></li><li class="h3 secondary ng-star-inserted" title="相对导航"><a href="guide/router#relative-navigation">相对导航</a></li><li class="h3 secondary ng-star-inserted" title="使用相对 URL 导航到危机列表"><a href="guide/router#navigate-to-crisis-list-with-a-relative-url">使用相对 URL 导航到危机列表</a></li><li class="h3 secondary ng-star-inserted" title="用命名出口（outlet）显示多重路由"><a href="guide/router#displaying-multiple-routes-in-named-outlets">用命名出口（outlet）显示多重路由</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 5：路由守卫"><a href="guide/router#milestone-5-route-guards">里程碑 5：路由守卫</a></li><li class="h3 secondary ng-star-inserted" title="CanActivate: 要求认证"><a href="guide/router#canactivate-requiring-authentication"><em>CanActivate</em>: 要求认证</a></li><li class="h3 secondary ng-star-inserted" title="CanActivateChild：保护子路由"><a href="guide/router#canactivatechild-guarding-child-routes"><code>CanActivateChild</code>：保护子路由</a></li><li class="h3 secondary ng-star-inserted" title="CanDeactivate：处理未保存的更改"><a href="guide/router#candeactivate-handling-unsaved-changes"><em>CanDeactivate</em>：处理未保存的更改</a></li><li class="h3 secondary ng-star-inserted" title="Resolve: 预先获取组件数据"><a href="guide/router#resolve-pre-fetching-component-data"><em>Resolve</em>: 预先获取组件数据</a></li><li class="h3 secondary ng-star-inserted" title="查询参数及片段"><a href="guide/router#query-parameters-and-fragments">查询参数及片段</a></li><li class="h2 secondary ng-star-inserted" title="里程碑 6：异步路由"><a href="guide/router#milestone-6-asynchronous-routing">里程碑 6：异步路由</a></li><li class="h3 secondary ng-star-inserted" title="惰性加载路由配置"><a href="guide/router#lazy-loading-route-configuration">惰性加载路由配置</a></li><li class="h3 secondary ng-star-inserted" title="CanLoad 守卫：保护对特性模块的未授权加载"><a href="guide/router#canload-guard-guarding-unauthorized-loading-of-feature-modules"><code>CanLoad</code> 守卫：保护对特性模块的未授权加载</a></li><li class="h3 secondary ng-star-inserted" title="预加载：特性区的后台加载"><a href="guide/router#preloading-background-loading-of-feature-areas">预加载：特性区的后台加载</a></li><li class="h3 secondary ng-star-inserted" title="自定义预加载策略"><a href="guide/router#custom-preloading-strategy">自定义预加载策略</a></li><li class="h2 secondary ng-star-inserted" title="使用重定向迁移 URL"><a href="guide/router#migrating-urls-with-redirects">使用重定向迁移 URL</a></li><li class="h3 secondary ng-star-inserted" title="把 /heroes 修改为 /superheros"><a href="guide/router#changing-heroes-to-superheroes">把 <code>/heroes</code> 修改为 <code>/superheros</code></a></li><li class="h2 secondary ng-star-inserted" title="审查路由器配置"><a href="guide/router#inspect-the-routers-configuration">审查路由器配置</a></li><li class="h2 secondary ng-star-inserted" title="总结与最终的应用"><a href="guide/router#wrap-up-and-final-app">总结与最终的应用</a></li><li class="h2 secondary ng-star-inserted" title="附录"><a href="guide/router#appendices">附录</a></li><li class="h3 secondary ng-star-inserted" title="附录：链接参数数组"><a href="guide/router#appendix-link-parameters-array">附录：链接参数数组</a></li><li class="h3 secondary ng-star-inserted" title="附录：LocationStrategy 以及浏览器 URL 样式"><a href="guide/router#appendix-locationstrategy-and-browser-url-styles">附录：<em>LocationStrategy</em> 以及浏览器 URL 样式</a></li></ul><button type="button" title="Expand/collapse contents" aria-label="Expand/collapse contents" class="toc-more-items embedded material-icons collapsed ng-star-inserted" aria-pressed="false"></button></div></aio-toc><h1 translation-origin="off" id="routing-and-navigation">Routing and navigation<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#routing-and-navigation"><i class="material-icons">link</i></a></h1><p translation-result="on">在用户使用应用程序时，Angular 的<strong><em>路由器</em></strong>能让用户从一个<a href="guide/glossary#view">视图</a>导航到另一个视图。</p><p translation-origin="off">The Angular <strong><code><a href="api/router/Router" class="code-anchor">Router</a></code></strong>enables navigation from one <a href="guide/glossary#view">view</a> to the next as users perform application tasks.</p><p translation-result="on">本章涵盖了该路由器的主要特性，通过一个小型应用的成长演进来讲解它。参见<live-example ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="现场演练" href="generated/live-examples/router/stackblitz.html">现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>。</p><p translation-origin="off">This guide covers the router's primary features, illustrating them through the evolution of a small application that you can<live-example ng-version="9.0.0-rc.11"><span style="display:none">run live in the browser</span><span><span class="ng-star-inserted"><a target="_blank" title="run live in the browser" href="generated/live-examples/router/stackblitz.html">run live in the browser</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>.</p><style>td,th{vertical-align:top}</style><h2 id="overview" translation-result="on">概览<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#overview"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="overview">Overview<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#overview"><i class="material-icons">link</i></a></h2><p translation-result="on">浏览器具有熟悉的导航模式：</p><p translation-origin="off">The browser is a familiar model of application navigation:</p><ul><li><p translation-result="on">在地址栏输入 URL，浏览器就会导航到相应的页面。</p><p translation-origin="off">Enter a URL in the address bar and the browser navigates to a corresponding page.</p></li><li><p translation-result="on">在页面中点击链接，浏览器就会导航到一个新页面。</p><p translation-origin="off">Click links on the page and the browser navigates to a new page.</p></li><li><p translation-result="on">点击浏览器的前进和后退按钮，浏览器就会在你的浏览历史中向前或向后导航。</p><p translation-origin="off">Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen.</p></li></ul><p translation-result="on">Angular 的 <code><a href="api/router/Router" class="code-anchor">Router</a></code>（即“路由器”）借鉴了这个模型。它把浏览器中的 URL 看做一个操作指南， 据此导航到一个由客户端生成的视图，并可以把参数传给支撑视图的相应组件，帮它决定具体该展现哪些内容。 你可以为页面中的链接绑定一个路由，这样，当用户点击链接时，就会导航到应用中相应的视图。 当用户点击按钮、从下拉框中选取，或响应来自任何地方的事件时，你也可以在代码控制下进行导航。 路由器还在浏览器的历史日志中记录下这些活动，这样浏览器的前进和后退按钮也能照常工作。</p><p translation-origin="off">The Angular <code><a href="api/router/Router" class="code-anchor">Router</a></code> ("the router") borrows from this model. It can interpret a browser URL as an instruction to navigate to a client-generated view. It can pass optional parameters along to the supporting view component that help it decide what specific content to present. You can bind the router to links on a page and it will navigate to the appropriate application view when the user clicks a link. You can navigate imperatively when the user clicks a button, selects from a drop box, or in response to some other stimulus from any source. And the router logs activity in the browser's history journal so the back and forward buttons work as well.</p><a id="basics"></a><h2 id="the-basics" translation-result="on">基础知识<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-basics"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="the-basics">The Basics<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-basics"><i class="material-icons">link</i></a></h2><p translation-result="on">本章包括一系列里程碑，从一个单模块、两个页面的简单程序逐步走向带有多个子路由的多视图设计。</p><p translation-origin="off">This guide proceeds in phases, marked by milestones, starting from a simple two-pager and building toward a modular, multi-view design with child routes.</p><p translation-result="on">先对路由的一些核心概念做一个介绍，它能帮你逐步过渡到细节。</p><p translation-origin="off">An introduction to a few core router concepts will help orient you to the details that follow.</p><a id="basics-base-href"></a><h3 id="base-href" translation-result="on"><em>&lt;base href&gt;</em> 元素<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#base-href"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="base-href"><em>&lt;base href&gt;</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#base-href"><i class="material-icons">link</i></a></h3><p translation-result="on">大多数带路由的应用都要在<strong><code>index.html</code></strong>的 <code>&lt;head&gt;</code> 标签下先添加一个 <code>&lt;base&gt;</code> 元素，来告诉路由器该如何合成导航用的 URL。</p><p translation-origin="off">Most routing applications should add a <code>&lt;base&gt;</code> element to the <code>index.html</code> as the first child in the <code>&lt;head&gt;</code> tag to tell the router how to compose navigation URLs.</p><p translation-result="on">如果 <code>app</code> 文件夹是该应用的根目录（就像范例应用中一样），那就把 <code>href</code> 的值设置为下面这样：</p><p translation-origin="off">If the <code>app</code> folder is the application root, as it is for the sample application, set the <code>href</code> value <em>exactly</em> as shown here.</p><code-example path="router/src/index.html" header="src/index.html (base-href)" region="base-href" ng-version="9.0.0-rc.11"><div style="display:none">&lt;base href="/"&gt;</div><header class="ng-star-inserted">src/index.html (base-href)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/index.html (base-href)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;base</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><a id="basics-router-imports"></a><h3 id="router-imports" translation-result="on">从路由库中导入<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-imports"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="router-imports">Router imports<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-imports"><i class="material-icons">link</i></a></h3><p translation-result="on">Angular 的路由器是一个可选的服务，它用来呈现指定的 URL 所对应的视图。 它并不是 Angular 核心库的一部分，而是在它自己的 <code>@angular/router</code> 包中。 像其它 Angular 包一样，你可以从它导入所需的一切。</p><p translation-origin="off">The Angular Router is an optional service that presents a particular component view for a given URL. It is not part of the Angular core. It is in its own library package, <code>@angular/router</code>. Import what you need from it as you would from any other Angular package.</p><code-example path="router/src/app/app.module.1.ts" header="src/app/app.module.ts (import)" region="import-router" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router';</div><header class="ng-star-inserted">src/app/app.module.ts (import)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (import)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">你将会在<a href="guide/router#browser-url-styles">后面</a>学到更多选项。</p><p translation-origin="off">You'll learn about more options in the <a href="guide/router#browser-url-styles">details below</a>.</p></div><a id="basics-config"></a><h3 id="configuration" translation-result="on">配置<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#configuration"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="configuration">Configuration<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#configuration"><i class="material-icons">link</i></a></h3><p translation-result="on">每个带路由的 Angular 应用都有一个<em><code><a href="api/router/Router" class="code-anchor">Router</a></code>（路由器）</em>服务的单例对象。 当浏览器的 URL 变化时，路由器会查找对应的 <code><a href="api/router/Route" class="code-anchor">Route</a></code>（路由），并据此决定该显示哪个组件。</p><p translation-origin="off">A routed Angular application has one singleton instance of the <em><code><a href="api/router/Router" class="code-anchor">Router</a></code></em>service. When the browser's URL changes, that router looks for a corresponding <code><a href="api/router/Route" class="code-anchor">Route</a></code> from which it can determine the component to display.</p><p translation-result="on">路由器需要先配置才会有路由信息。 下面的例子创建了五个路由定义，并用 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 方法来配置路由器， 并把它的返回值添加到 <code>AppModule</code> 的 <code>imports</code> 数组中。</p><p translation-origin="off">A router has no routes until you configure it. The following example creates five route definitions, configures the router via the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> method, and adds the result to the <code>AppModule</code>'s <code>imports</code> array.</p><code-example path="router/src/app/app.module.0.ts" header="src/app/app.module.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes <a href="api/common/NumberSymbol#List" class="code-anchor">List</a>' } }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) // other imports here ], ... }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln">      component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln">
    data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> title</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Heroes </span><a href="api/common/NumberSymbol#List" class="code-anchor"><span class="str">List</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
    </span><span class="com">// other imports here</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><a id="example-config"></a><p translation-result="on">这里的路由数组 <code>appRoutes</code> 描述如何进行导航。 把它传给 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 方法并传给本模块的 <code>imports</code> 数组就可以配置路由器。</p><p translation-origin="off">The <code>appRoutes</code> array of <em>routes</em> describes how to navigate. Pass it to the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> method in the module <code>imports</code> to configure the router.</p><p translation-result="on">每个 <code><a href="api/router/Route" class="code-anchor">Route</a></code> 都会把一个 URL 的 <code>path</code> 映射到一个组件。 注意，<code>path</code> 不能以<em>斜杠（<code>/</code>）</em>开头。 路由器会为解析和构建最终的 URL，这样当你在应用的多个视图之间导航时，可以任意使用相对路径和绝对路径。</p><p translation-origin="off">Each <code><a href="api/router/Route" class="code-anchor">Route</a></code> maps a URL <code>path</code> to a component. There are <em>no leading slashes</em> in the <em>path</em>. The router parses and builds the final URL for you, allowing you to use both relative and absolute paths when navigating between application views.</p><p translation-result="on">第二个路由中的 <code>:id</code> 是一个路由参数的令牌(Token)。比如 <code>/hero/42</code> 这个 URL 中，“42”就是 <code>id</code> 参数的值。 此 URL 对应的 <code>HeroDetailComponent</code> 组件将据此查找和展现 <code>id</code> 为 42 的英雄。 在本章中稍后的部分，你将会学习关于路由参数的更多知识。</p><p translation-origin="off">The <code>:id</code> in the second route is a token for a route parameter. In a URL such as <code>/hero/42</code>, "42" is the value of the <code>id</code> parameter. The corresponding <code>HeroDetailComponent</code> will use that value to find and present the hero whose <code>id</code> is 42. You'll learn more about route parameters later in this guide.</p><p translation-result="on">第三个路由中的 <code>data</code> 属性用来存放于每个具体路由有关的任意信息。该数据可以被任何一个激活路由访问，并能用来保存诸如 页标题、面包屑以及其它静态只读数据。本章稍后的部分，你将使用<a href="guide/router#resolve-guard">resolve 守卫</a>来获取动态数据。</p><p translation-origin="off">The <code>data</code> property in the third route is a place to store arbitrary data associated with this specific route. The data property is accessible within each activated route. Use it to store items such as page titles, breadcrumb text, and other read-only, <em>static</em> data. You'll use the <a href="guide/router#resolve-guard">resolve guard</a> to retrieve <em>dynamic</em> data later in the guide.</p><p translation-result="on">第四个路由中的空路径（<code>''</code>）表示应用的默认路径，当 URL 为空时就会访问那里，因此它通常会作为起点。 这个默认路由会重定向到 URL <code>/heroes</code>，并显示 <code>HeroesListComponent</code>。</p><p translation-origin="off">The <strong>empty path</strong> in the fourth route represents the default path for the application, the place to go when the path in the URL is empty, as it typically is at the start. This default route redirects to the route for the <code>/heroes</code> URL and, therefore, will display the <code>HeroesListComponent</code>.</p><p translation-result="on">最后一个路由中的 <code>**</code> 路径是一个<strong>通配符</strong>。当所请求的 URL 不匹配前面定义的路由表中的任何路径时，路由器就会选择此路由。 这个特性可用于显示“404 - Not Found”页，或自动重定向到其它路由。</p><p translation-origin="off">The <code>**</code> path in the last route is a <strong>wildcard</strong>. The router will select this route if the requested URL doesn't match any paths for routes defined earlier in the configuration. This is useful for displaying a "404 - Not Found" page or redirecting to another route.</p><p translation-result="on"><strong>这些路由的定义顺序</strong>是刻意如此设计的。路由器使用<strong>先匹配者优先</strong>的策略来匹配路由，所以，具体路由应该放在通用路由的前面。在上面的配置中，带静态路径的路由被放在了前面，后面是空路径路由，因此它会作为默认路由。而通配符路由被放在最后面，这是因为它能匹配上<em>每一个 URL</em>，因此应该<strong>只有在</strong>前面找不到其它能匹配的路由时才匹配它。</p><p translation-origin="off"><strong>The order of the routes in the configuration matters</strong> and this is by design. The router uses a <strong>first-match wins</strong> strategy when matching routes, so more specific routes should be placed above less specific routes. In the configuration above, routes with a static path are listed first, followed by an empty path route, that matches the default route. The wildcard route comes last because it matches <em>every URL</em> and should be selected <em>only</em> if no other routes are matched first.</p><p translation-result="on">如果你想要看到在导航的生命周期中发生过哪些事件，可以使用路由器默认配置中的 <strong>enableTracing</strong> 选项。它会把每个导航生命周期中的事件输出到浏览器的控制台。 这应该只用于<em>调试</em>。你只需要把 <code><a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true</code> 选项作为第二个参数传给 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 方法就可以了。</p><p translation-origin="off">If you need to see what events are happening during the navigation lifecycle, there is the <strong>enableTracing</strong> option as part of the router's default configuration. This outputs each router event that took place during each navigation lifecycle to the browser console. This should only be used for <em>debugging</em> purposes. You set the <code><a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true</code> option in the object passed as the second argument to the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> method.</p><a id="basics-router-outlet"></a><h3 id="router-outlet" translation-result="on">路由出口<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-outlet"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="router-outlet">Router outlet<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-outlet"><i class="material-icons">link</i></a></h3><p translation-result="on"><code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 是一个来自路由模块中的指令，它的用法类似于组件。 它扮演一个占位符的角色，用于在模板中标出一个位置，路由器将会把要显示在这个出口处的组件显示在这里。</p><p translation-origin="off">The <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> is a directive from the router library that is used like a component. It acts as a placeholder that marks the spot in the template where the router should display the components for that outlet.</p><code-example language="html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;!-- Routed <a href="api/core/ApplicationRef#components" class="code-anchor">components</a> go here --&gt;</div><aio-code><pre class="lang-html prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="com">&lt;!-- Routed </span><a href="api/core/ApplicationRef#components" class="code-anchor"><span class="com">components</span></a><span class="com"> go here --&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">有了这份配置，当本应用在浏览器中的 URL 变为 <code>/heroes</code> 时，路由器就会匹配到 <code>path</code> 为 <code>heroes</code> 的 <code><a href="api/router/Route" class="code-anchor">Route</a></code>，并在宿主视图中的<em><code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code></em>之后显示 <code>HeroListComponent</code> 组件。</p><p translation-origin="off">Given the configuration above, when the browser URL for this application becomes <code>/heroes</code>, the router matches that URL to the route path <code>/heroes</code> and displays the <code>HeroListComponent</code> as a sibling element to the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> that you've placed in the host component's template.</p><a id="basics-router-links"></a> <a id="router-link"></a><h3 id="router-links" translation-result="on">路由器链接<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-links"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="router-links">Router links<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-links"><i class="material-icons">link</i></a></h3><p translation-result="on">现在，你已经有了配置好的一些路由，还找到了渲染它们的地方，但又该如何导航到它呢？固然，从浏览器的地址栏直接输入 URL 也能做到，但是大多数情况下，导航是某些用户操作的结果，比如点击一个 A 标签。</p><p translation-origin="off">Now you have routes configured and a place to render them, but how do you navigate? The URL could arrive directly from the browser address bar. But most of the time you navigate as a result of some user action such as the click of an anchor tag.</p><p translation-result="on">考虑下列模板：</p><p translation-origin="off">Consider the following template:</p><code-example path="router/src/app/app.component.1.html" header="src/app/app.component.html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h1&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;/nav&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/app.component.html</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code><a href="api/router/RouterLinkWithHref" class="code-anchor">a</a></code> 标签上的 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令让路由器得以控制这个 <code><a href="api/router/RouterLinkWithHref" class="code-anchor">a</a></code> 元素。 这里的导航路径是固定的，因此可以把一个字符串赋给 <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code>（“一次性”绑定）。</p><p translation-origin="off">The <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directives on the anchor tags give the router control over those elements. The navigation paths are fixed, so you can assign a string to the <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> (a "one-time" binding).</p><p translation-result="on">如果需要更加动态的导航路径，那就把它绑定到一个返回<em>链接参数数组</em>的模板表达式。 路由器会把这个数组解析成完整的 URL。</p><p translation-origin="off">Had the navigation path been more dynamic, you could have bound to a template expression that returned an array of route link parameters (the <em>link parameters array</em>). The router resolves that array into a complete URL.</p><a id="router-link-active"></a><h3 id="active-router-links" translation-result="on">路由链接的激活状态<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#active-router-links"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="active-router-links">Active router links<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#active-router-links"><i class="material-icons">link</i></a></h3><p translation-result="on"><code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> 指令会基于当前的 <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> 为活动的 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 切换所绑定的 css 类。</p><p translation-origin="off">The <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> directive toggles css classes for active <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> bindings based on the current <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code>.</p><p translation-result="on">在每个 A 标签上，你会看到一个到 <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> 的<a href="guide/template-syntax#property-binding">属性绑定</a>，形如 <code><a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="..."</code>。</p><p translation-origin="off">On each anchor tag, you see a <a href="guide/template-syntax#property-binding">property binding</a> to the <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> directive that look like <code><a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="..."</code>.</p><p translation-result="on">等号右边的模板表达式包含一些用空格分隔的 CSS 类名，当这个链接激活时，路由器将会把它们加上去（并在处于非活动状态时移除）。你还可以把 <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> 设置为一个类组成的字符串，如 <code>[<a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>]="'active fluffy'"</code>，或把它绑定到一个返回类似字符串的组件属性。</p><p translation-origin="off">The template expression to the right of the equals (=) contains a space-delimited string of CSS classes that the Router will add when this link is active (and remove when the link is inactive). You set the <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code> directive to a string of classes such as <code>[<a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>]="'active fluffy'"</code> or bind it to a component property that returns such a string.</p><p translation-result="on">路由链接的激活状态会向下级联到路由树中的每个层级，所以，父子路由链接可能会同时激活。要覆盖这种行为，可以把 <code>[<a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor">routerLinkActiveOptions</a>]</code> 绑定为 <code>{ exact: true }</code> 表达式，这样 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 只有当 URL 与当前 URL 精确匹配时才会激活。</p><p translation-origin="off">Active route links cascade down through each level of the route tree, so parent and child router links can be active at the same time. To override this behavior, you can bind to the <code>[<a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor">routerLinkActiveOptions</a>]</code> input binding with the <code>{ exact: true }</code> expression. By using <code>{ exact: true }</code>, a given <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> will only be active if its URL is an exact match to the current URL.</p><a id="basics-router-state"></a><h3 id="router-state" translation-result="on">路由器状态<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-state"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="router-state">Router state<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-state"><i class="material-icons">link</i></a></h3><p translation-result="on">在导航时的每个生命周期成功完成时，路由器会构建出一个 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 组成的树，它表示路由器的当前状态。 你可以在应用中的任何地方用 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务及其 <code><a href="api/router/Router#routerState" class="code-anchor">routerState</a></code> 属性来访问当前的 <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> 值。</p><p translation-origin="off">After the end of each successful navigation lifecycle, the router builds a tree of <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> objects that make up the current state of the router. You can access the current <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> from anywhere in the application using the <code><a href="api/router/Router" class="code-anchor">Router</a></code> service and the <code><a href="api/router/Router#routerState" class="code-anchor">routerState</a></code> property.</p><p translation-result="on"><code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> 中的每个 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 都提供了从任意激活路由开始向上或向下遍历路由树的一种方式，以获得关于父、子、兄弟路由的信息。</p><p translation-origin="off">Each <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> in the <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> provides methods to traverse up and down the route tree to get information from parent, child and sibling routes.</p><a id="activated-route"></a><h3 id="activated-route" translation-result="on">激活的路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#activated-route"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="activated-route">Activated route<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#activated-route"><i class="material-icons">link</i></a></h3><p translation-result="on">该路由的路径和参数可以通过注入进来的一个名叫<a href="api/router/ActivatedRoute">ActivatedRoute</a>的路由服务来获取。 它有一大堆有用的信息，包括：</p><p translation-origin="off">The route path and parameters are available through an injected router service called the <a href="api/router/ActivatedRoute">ActivatedRoute</a>. It has a great deal of useful information including:</p><table><tbody><tr><th><p translation-result="on">属性</p><p translation-origin="off">Property</p></th><th><p translation-result="on">说明</p><p translation-origin="off">Description</p></th></tr><tr><td><p> <code>url</code></p></td><td><p translation-result="on">路由路径的 <code>Observable</code> 对象，是一个由路由路径中的各个部分组成的字符串数组。</p><p translation-origin="off">An <code>Observable</code> of the route path(s), represented as an array of strings for each part of the route path.</p></td></tr><tr><td><p> <code>data</code></p></td><td><p translation-result="on">一个 <code>Observable</code>，其中包含提供给路由的 <code>data</code> 对象。也包含由<a href="guide/router#resolve-guard">解析守卫（resolve guard）</a>解析而来的值。</p><p translation-origin="off">An <code>Observable</code> that contains the <code>data</code> object provided for the route. Also contains any resolved values from the <a href="guide/router#resolve-guard">resolve guard</a>.</p></td></tr><tr><td><p> <code>paramMap</code></p></td><td><p translation-result="on">一个 <code>Observable</code>，其中包含一个由当前路由的必要参数和<a href="guide/router#optional-route-parameters">可选参数</a>组成的<a href="api/router/ParamMap">map</a>对象。用这个 map 可以获取来自同名参数的单一值或多重值。</p><p translation-origin="off">An <code>Observable</code> that contains a <a href="api/router/ParamMap">map</a> of the required and <a href="guide/router#optional-route-parameters">optional parameters</a> specific to the route. The map supports retrieving single and multiple values from the same parameter.</p></td></tr><tr><td><p> <code>queryParamMap</code></p></td><td><p translation-result="on">一个 <code>Observable</code>，其中包含一个对所有路由都有效的<a href="guide/router#query-parameters">查询参数</a>组成的<a href="api/router/ParamMap">map</a>对象。 用这个 map 可以获取来自查询参数的单一值或多重值。</p><p translation-origin="off">An <code>Observable</code> that contains a <a href="api/router/ParamMap">map</a> of the <a href="guide/router#query-parameters">query parameters</a> available to all routes. The map supports retrieving single and multiple values from the query parameter.</p></td></tr><tr><td><p> <code>fragment</code></p></td><td><p translation-result="on">一个适用于所有路由的 URL 的 <a href="guide/router#fragment">fragment（片段）</a>的 <code>Observable</code>。</p><p translation-origin="off">An <code>Observable</code> of the URL <a href="guide/router#fragment">fragment</a> available to all routes.</p></td></tr><tr><td><p> <code>outlet</code></p></td><td><p translation-result="on">要把该路由渲染到的 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 的名字。对于无名路由，它的路由名是 <code>primary</code>，而不是空串。</p><p translation-origin="off">The name of the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> used to render the route. For an unnamed outlet, the outlet name is <em>primary</em>.</p></td></tr><tr><td><p> <code>routeConfig</code></p></td><td><p translation-result="on">用于该路由的路由配置信息，其中包含原始路径。</p><p translation-origin="off">The route configuration used for the route that contains the origin path.</p></td></tr><tr><td><p> <code>parent</code></p></td><td><p translation-result="on">当该路由是一个<a href="guide/router#child-routing-component">子路由</a>时，表示该路由的父级 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>。</p><p translation-origin="off">The route's parent <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> when this route is a <a href="guide/router#child-routing-component">child route</a>.</p></td></tr><tr><td><p> <code>firstChild</code></p></td><td><p translation-result="on">包含该路由的子路由列表中的第一个 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>。</p><p translation-origin="off">Contains the first <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> in the list of this route's child routes.</p></td></tr><tr><td><p> <code>children</code></p></td><td><p translation-result="on">包含当前路由下所有已激活的<a href="guide/router#child-routing-component">子路由</a>。</p><p translation-origin="off">Contains all the <a href="guide/router#child-routing-component">child routes</a> activated under the current route.</p></td></tr></tbody></table><div class="alert is-helpful"><p translation-result="on">有两个旧式属性仍然是有效的，但它们不如其替代品那样强力，建议不再用它们，它们还将在未来的 Angular 版本中废弃。</p><p translation-origin="off">Two older properties are still available. They are less capable than their replacements, discouraged, and may be deprecated in a future Angular version.</p><p translation-result="on"><strong><code>params</code></strong>—— 一个 <code>Observable</code> 对象，其中包含当前路由的必要参数和<a href="guide/router#optional-route-parameters">可选参数</a>。请改用 <code>paramMap</code>。</p><p translation-origin="off"><strong><code>params</code></strong>—An <code>Observable</code> that contains the required and <a href="guide/router#optional-route-parameters">optional parameters</a> specific to the route. Use <code>paramMap</code> instead.</p><p translation-result="on"><strong><code>queryParams</code></strong>—— 一个 <code>Observable</code> 对象，其中包含对所有路由都有效的<a href="guide/router#query-parameters">查询参数</a>。请改用 <code>queryParamMap</code>。</p><p translation-origin="off"><strong><code>queryParams</code></strong>—An <code>Observable</code> that contains the <a href="guide/router#query-parameters">query parameters</a> available to all routes. Use <code>queryParamMap</code> instead.</p></div><h3 id="router-events" translation-result="on">路由事件<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-events"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="router-events">Router events<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#router-events"><i class="material-icons">link</i></a></h3><p translation-result="on">在每次导航中，<code><a href="api/router/Router" class="code-anchor">Router</a></code> 都会通过 <code><a href="api/router/Router#events" class="code-anchor">Router.events</a></code> 属性发布一些导航事件。这些事件的范围涵盖了从开始导航到结束导航之间的很多时间点。下表中列出了全部导航事件：</p><p translation-origin="off">During each navigation, the <code><a href="api/router/Router" class="code-anchor">Router</a></code> emits navigation events through the <code><a href="api/router/Router#events" class="code-anchor">Router.events</a></code> property. These events range from when the navigation starts and ends to many points in between. The full list of navigation events is displayed in the table below.</p><table><tbody><tr><th><p translation-result="on">路由器事件</p><p translation-origin="off">Router Event</p></th><th><p translation-result="on">说明</p><p translation-origin="off">Description</p></th></tr><tr><td><p> <code><a href="api/router/NavigationStart" class="code-anchor">NavigationStart</a></code></p></td><td><p translation-result="on">本<a href="api/router/NavigationStart">事件</a>会在导航开始时触发。</p><p translation-origin="off">An <a href="api/router/NavigationStart">event</a> triggered when navigation starts.</p></td></tr><tr><td> <code><a href="api/router/RouteConfigLoadStart" class="code-anchor">RouteConfigLoadStart</a></code> </td><td><p translation-result="on">本<a href="api/router/RouteConfigLoadStart">事件</a>会在 <code><a href="api/router/Router" class="code-anchor">Router</a></code> <a href="guide/router#asynchronous-routing">惰性加载</a> 某个路由配置之前触发。</p><p translation-origin="off">An <a href="api/router/RouteConfigLoadStart">event</a> triggered before the <code><a href="api/router/Router" class="code-anchor">Router</a></code> <a href="guide/router#asynchronous-routing">lazy loads</a> a route configuration.</p></td></tr><tr><td> <code><a href="api/router/RouteConfigLoadEnd" class="code-anchor">RouteConfigLoadEnd</a></code> </td><td><p translation-result="on">本<a href="api/router/RouteConfigLoadEnd">事件</a>会在惰性加载了某个路由后触发。</p><p translation-origin="off">An <a href="api/router/RouteConfigLoadEnd">event</a> triggered after a route has been lazy loaded.</p></td></tr><tr><td><p> <code><a href="api/router/RoutesRecognized" class="code-anchor">RoutesRecognized</a></code></p></td><td><p translation-result="on">本<a href="api/router/RoutesRecognized">事件</a>会在路由器解析完 URL，并识别出了相应的路由时触发</p><p translation-origin="off">An <a href="api/router/RoutesRecognized">event</a> triggered when the Router parses the URL and the routes are recognized.</p></td></tr><tr><td><p> <code><a href="api/router/GuardsCheckStart" class="code-anchor">GuardsCheckStart</a></code></p></td><td><p translation-result="on">本<a href="api/router/GuardsCheckStart">事件</a>会在路由器开始 Guard 阶段之前触发。</p><p translation-origin="off">An <a href="api/router/GuardsCheckStart">event</a> triggered when the Router begins the Guards phase of routing.</p></td></tr><tr><td> <code><a href="api/router/ChildActivationStart" class="code-anchor">ChildActivationStart</a></code> </td><td><p translation-result="on">本<a href="api/router/ChildActivationStart">事件</a>会在路由器开始激活路由的子路由时触发。</p><p translation-origin="off">An <a href="api/router/ChildActivationStart">event</a> triggered when the Router begins activating a route's children.</p></td></tr><tr><td> <code><a href="api/router/ActivationStart" class="code-anchor">ActivationStart</a></code> </td><td><p translation-result="on">本<a href="api/router/ActivationStart">事件</a>会在路由器开始激活某个路由时触发。</p><p translation-origin="off">An <a href="api/router/ActivationStart">event</a> triggered when the Router begins activating a route.</p></td></tr><tr><td> <code><a href="api/router/GuardsCheckEnd" class="code-anchor">GuardsCheckEnd</a></code> </td><td><p translation-result="on">本<a href="api/router/GuardsCheckEnd">事件</a>会在路由器成功完成了 Guard 阶段时触发。</p><p translation-origin="off">An <a href="api/router/GuardsCheckEnd">event</a> triggered when the Router finishes the Guards phase of routing successfully.</p></td></tr><tr><td> <code><a href="api/router/ResolveStart" class="code-anchor">ResolveStart</a></code> </td><td><p translation-result="on">本<a href="api/router/ResolveStart">事件</a>会在 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 开始解析（Resolve）阶段时触发。</p><p translation-origin="off">An <a href="api/router/ResolveStart">event</a> triggered when the Router begins the Resolve phase of routing.</p></td></tr><tr><td><p> <code><a href="api/router/ResolveEnd" class="code-anchor">ResolveEnd</a></code></p></td><td><p translation-result="on">本<a href="api/router/ResolveEnd">事件</a>会在路由器成功完成了路由的解析（Resolve）阶段时触发。</p><p translation-origin="off">An <a href="api/router/ResolveEnd">event</a> triggered when the Router finishes the Resolve phase of routing successfuly.</p></td></tr><tr><td> <code><a href="api/router/ChildActivationEnd" class="code-anchor">ChildActivationEnd</a></code> </td><td><p translation-result="on">本<a href="api/router/ChildActivationEnd">事件</a>会在路由器激活了路由的子路由时触发。</p><p translation-origin="off">An <a href="api/router/ChildActivationEnd">event</a> triggered when the Router finishes activating a route's children.</p></td></tr><tr><td> <code><a href="api/router/ActivationEnd" class="code-anchor">ActivationEnd</a></code> </td><td><p translation-result="on">本<a href="api/router/ActivationStart">事件</a>会在路由器激活了某个路由时触发。</p><p translation-origin="off">An <a href="api/router/ActivationStart">event</a> triggered when the Router finishes activating a route.</p></td></tr><tr><td><p> <code><a href="api/router/NavigationEnd" class="code-anchor">NavigationEnd</a></code></p></td><td><p translation-result="on">本<a href="api/router/NavigationEnd">事件</a>会在导航成功结束之后触发。</p><p translation-origin="off">An <a href="api/router/NavigationEnd">event</a> triggered when navigation ends successfully.</p></td></tr><tr><td><p> <code><a href="api/router/NavigationCancel" class="code-anchor">NavigationCancel</a></code></p></td><td><p translation-result="on">本<a href="api/router/NavigationCancel">事件</a>会在导航被取消之后触发。 这可能是因为在导航期间某个<a href="guide/router#guards">路由守卫</a>返回了 <code>false</code>。</p><p translation-origin="off">An <a href="api/router/NavigationCancel">event</a> triggered when navigation is canceled. This can happen when a <a href="guide/router#guards">Route Guard</a> returns false during navigation, or redirects by returning a <code><a href="api/router/UrlTree" class="code-anchor">UrlTree</a></code>.</p></td></tr><tr><td><p> <code><a href="api/router/NavigationError" class="code-anchor">NavigationError</a></code></p></td><td><p translation-result="on">这个<a href="api/router/NavigationError">事件</a>会在导航由于意料之外的错误而失败时触发。</p><p translation-origin="off">An <a href="api/router/NavigationError">event</a> triggered when navigation fails due to an unexpected error.</p></td></tr><tr><td> <code><a href="api/router/Scroll" class="code-anchor">Scroll</a></code> </td><td><p translation-result="on">本<a href="api/router/Scroll">事件</a>代表一个滚动事件。</p><p translation-origin="off">An <a href="api/router/Scroll">event</a> that represents a scrolling event.</p></td></tr></tbody></table><p translation-result="on">当启用了 <code><a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a></code> 选项时，这些事件也同时会记录到控制台中。要想查看对路由导航事件进行过滤的例子，请访问 <a href="guide/observables-in-angular">Angular 中的可观察对象</a>一章的<a href="guide/observables-in-angular#router">路由器部分</a></p><p translation-origin="off">These events are logged to the console when the <code><a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a></code> option is enabled also. For an example of filtering router navigation events, visit the <a href="guide/observables-in-angular#router">router section</a> of the <a href="guide/observables-in-angular">Observables in Angular</a> guide.</p><a id="basics-summary"></a><h3 id="summary" translation-result="on">总结一下<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#summary"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="summary">Summary<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#summary"><i class="material-icons">link</i></a></h3><p translation-result="on">该应用有一个配置过的路由器。 外壳组件中有一个 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>，它能显示路由器所生成的视图。 它还有一些 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>，用户可以点击它们，来通过路由器进行导航。</p><p translation-origin="off">The application has a configured router. The shell component has a <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> where it can display views produced by the router. It has <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>s that users can click to navigate via the router.</p><p translation-result="on">下面是一些<em>路由器</em>中的关键词汇及其含义：</p><p translation-origin="off">Here are the key <code><a href="api/router/Router" class="code-anchor">Router</a></code> terms and their meanings:</p><table><tbody><tr><th><p translation-result="on">路由器部件</p><p translation-origin="off">Router Part</p></th><th><p translation-result="on">含义</p><p translation-origin="off">Meaning</p></th></tr><tr><td><p translation-result="on"> <code><a href="api/router/Router" class="code-anchor">Router</a></code>（路由器）</p><p translation-origin="off"> <code><a href="api/router/Router" class="code-anchor">Router</a></code></p></td><td><p translation-result="on">为激活的 URL 显示应用组件。管理从一个组件到另一个组件的导航</p><p translation-origin="off">Displays the application component for the active URL. Manages navigation from one component to the next.</p></td></tr><tr><td><p> <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code></p></td><td><p translation-result="on">一个独立的 NgModule，用于提供所需的服务提供者，以及用来在应用视图之间进行导航的指令。</p><p translation-origin="off">A separate NgModule that provides the necessary service providers and directives for navigating through application views.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/Routes" class="code-anchor">Routes</a></code>（路由数组）</p><p translation-origin="off"> <code><a href="api/router/Routes" class="code-anchor">Routes</a></code></p></td><td><p translation-result="on">定义了一个路由数组，每一个都会把一个 URL 路径映射到一个组件。</p><p translation-origin="off">Defines an array of Routes, each mapping a URL path to a component.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/Route" class="code-anchor">Route</a></code>（路由）</p><p translation-origin="off"> <code><a href="api/router/Route" class="code-anchor">Route</a></code></p></td><td><p translation-result="on">定义路由器该如何根据 URL 模式（pattern）来导航到组件。大多数路由都由路径和组件类构成。</p><p translation-origin="off">Defines how the router should navigate to a component based on a URL pattern. Most routes consist of a path and a component type.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>（路由出口）</p><p translation-origin="off"> <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code></p></td><td><p translation-result="on">该指令（<code>&lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code>）用来标记出路由器该在哪里显示视图。</p><p translation-origin="off">The directive (<code>&lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code>) that marks where the router displays a view.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>（路由链接）</p><p translation-origin="off"> <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code></p></td><td><p translation-result="on">这个指令把可点击的 HTML 元素绑定到某个路由。点击带有 <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> 指令（绑定到<i>字符串</i>或<i>链接参数数组</i>）的元素时就会触发一次导航。</p><p translation-origin="off">The directive for binding a clickable HTML element to a route. Clicking an element with a <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> directive that is bound to a <i>string</i> or a <i>link parameters array</i> triggers a navigation.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code>（活动路由链接）</p><p translation-origin="off"> <code><a href="api/router/RouterLinkActive" class="code-anchor">RouterLinkActive</a></code></p></td><td><p translation-result="on">当 HTML 元素上或元素内的<code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code>变为激活或非激活状态时，该指令为这个 HTML 元素添加或移除 CSS 类。</p><p translation-origin="off">The directive for adding/removing classes from an HTML element when an associated <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> contained on or inside the element becomes active/inactive.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>（激活的路由）</p><p translation-origin="off"> <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code></p></td><td><p translation-result="on">为每个路由组件提供的一个服务，它包含特定于路由的信息，比如路由参数、静态数据、解析数据、全局查询参数和全局碎片（fragment）。</p><p translation-origin="off">A service that is provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query params, and the global fragment.</p></td></tr><tr><td><p translation-result="on"> <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code>（路由器状态）</p><p translation-origin="off"> <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code></p></td><td><p translation-result="on">路由器的当前状态包含了一棵由程序中激活的路由构成的树。它包含一些用于遍历路由树的快捷方法。</p><p translation-origin="off">The current state of the router including a tree of the currently activated routes together with convenience methods for traversing the route tree.</p></td></tr><tr><td><p translation-result="on"><b><i>链接参数数组</i></b></p><p translation-origin="off"><b><i>Link parameters array</i></b></p></td><td><p translation-result="on">这个数组会被路由器解释成一个路由操作指南。你可以把一个<code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>绑定到该数组，或者把它作为参数传给<code>Router.navigate</code>方法。</p><p translation-origin="off">An array that the router interprets as a routing instruction. You can bind that array to a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> or pass the array as an argument to the <code>Router.navigate</code> method.</p></td></tr><tr><td><p translation-result="on"><b><i>路由组件</i></b></p><p translation-origin="off"><b><i>Routing component</i></b></p></td><td><p translation-result="on">一个带有<code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>的 Angular 组件，它根据路由器的导航来显示相应的视图。</p><p translation-origin="off">An Angular component with a <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> that displays views based on router navigations.</p></td></tr></tbody></table><a id="sample-app-intro"></a><h2 id="the-sample-application" translation-result="on">范例应用<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-sample-application"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="the-sample-application">The sample application<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-sample-application"><i class="material-icons">link</i></a></h2><p translation-result="on">本章要讲的是如何开发一个带路由的多页面应用。 接下来会重点讲它的设计决策，并描述路由的关键特性，比如：</p><p translation-origin="off">This guide describes development of a multi-page routed sample application. Along the way, it highlights design decisions and describes key features of the router such as:</p><ul><li><p translation-result="on">把应用的各个特性组织成模块。</p><p translation-origin="off">Organizing the application features into modules.</p></li><li><p translation-result="on">导航到组件（<em>Heroes</em> 链接到“英雄列表”组件）。</p><p translation-origin="off">Navigating to a component (<em>Heroes</em> link to "Heroes List").</p></li><li><p translation-result="on">包含一个路由参数（当路由到“英雄详情”时，把该英雄的 <code>id</code> 传进去）。</p><p translation-origin="off">Including a route parameter (passing the Hero <code>id</code> while routing to the "Hero Detail").</p></li><li><p translation-result="on">子路由（<em>危机中心</em>特性有一组自己的路由）。</p><p translation-origin="off">Child routes (the <em>Crisis Center</em> has its own routes).</p></li><li><p translation-result="on"> <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> 守卫（检查路由的访问权限）。</p><p translation-origin="off">The <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> guard (checking route access).</p></li><li><p translation-result="on"> <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 守卫（检查子路由的访问权限）。</p><p translation-origin="off">The <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> guard (checking child route access).</p></li><li><p translation-result="on"> <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> 守卫（询问是否丢弃未保存的更改）。</p><p translation-origin="off">The <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> guard (ask permission to discard unsaved changes).</p></li><li><p translation-result="on"> <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> 守卫（预先获取路由数据）。</p><p translation-origin="off">The <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> guard (pre-fetching route data).</p></li><li><p translation-result="on">惰性加载特性模块。</p><p translation-origin="off">Lazy loading feature modules.</p></li><li><p translation-result="on"> <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 守卫（在加载特性模块之前进行检查）。</p><p translation-origin="off">The <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> guard (check before loading feature module assets).</p></li></ul><p translation-result="on">如果打算一步步构建出本应用，本章就会经过一系列里程碑。 但是，本章并不是一个教程，它隐藏了构造 Angular 应用的细节，那些细节会在本文档的其它地方展开。</p><p translation-origin="off">The guide proceeds as a sequence of milestones as if you were building the app step-by-step. But, it is not a tutorial and it glosses over details of Angular application construction that are more thoroughly covered elsewhere in the documentation.</p><p translation-result="on">本应用的最终版源码可以在<live-example ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="现场演练" href="generated/live-examples/router/stackblitz.html">现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>中查看和下载。</p><p translation-origin="off">The full source for the final version of the app can be seen and downloaded from the<live-example ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="现场演练" href="generated/live-examples/router/stackblitz.html">现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>.</p><h3 id="the-sample-application-in-action" translation-result="on">范例程序的动图<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-sample-application-in-action"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="the-sample-application-in-action">The sample application in action<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-sample-application-in-action"><i class="material-icons">link</i></a></h3><p translation-result="on">假设本程序会用来帮助“英雄管理局”运行他们的业务。 英雄们需要找工作，而“英雄管理局”为他们寻找待解决的危机。</p><p translation-origin="off">Imagine an application that helps the <em>Hero Employment Agency</em> run its business. Heroes need work and the agency finds crises for them to solve.</p><p translation-result="on">本应用具有三个主要的特性区：</p><p translation-origin="off">The application has three main feature areas:</p><ol><li><p translation-result="on"><em>危机中心</em>用于维护要指派给英雄的危机列表。</p><p translation-origin="off">A <em>Crisis Center</em> for maintaining the list of crises for assignment to heroes.</p></li><li><p translation-result="on"><em>英雄</em>区用于维护管理局雇佣的英雄列表。</p><p translation-origin="off">A <em>Heroes</em> area for maintaining the list of heroes employed by the agency.</p></li><li><p translation-result="on"><em>管理</em>区会管理危机和英雄的列表。</p><p translation-origin="off">An <em>Admin</em> area to manage the list of crises and heroes.</p></li></ol><p translation-result="on">点击<live-example title="英雄职介中心的现场演练" ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="英雄职介中心的现场演练" href="generated/live-examples/router/stackblitz.html">英雄职介中心的现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>试用一下。</p><p translation-origin="off">Try it by clicking on this<live-example title="Hero Employment Agency Live Example" ng-version="9.0.0-rc.11"><span style="display:none">live example link</span><span><span class="ng-star-inserted"><a target="_blank" title="live example link" href="generated/live-examples/router/stackblitz.html">live example link</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>.</p><p translation-result="on">等应用热身完毕，你就会看到一排导航按钮，以及一个<em>英雄列表</em>视图。</p><p translation-origin="off">Once the app warms up, you'll see a row of navigation buttons and the <em>Heroes</em> view with its list of heroes.</p><div class="lightbox"><img src="generated/images/guide/router/hero-list.png" alt="Hero List" width="250" height="225"></div><p translation-result="on">选择其中之一，该应用就会把你带到此英雄的编辑页面。</p><p translation-origin="off">Select one hero and the app takes you to a hero editing screen.</p><div class="lightbox"><img src="generated/images/guide/router/hero-detail.png" alt="Crisis Center Detail" width="250" height="162"></div><p translation-result="on">修改完名字，再点击“后退”按钮，应用又回到了英雄列表页，其中显示的英雄名已经变了。注意，对名字的修改会立即生效。</p><p translation-origin="off">Alter the name. Click the "Back" button and the app returns to the heroes list which displays the changed hero name. Notice that the name change took effect immediately.</p><p translation-result="on">另外你也可以点击浏览器本身的后退按钮，这样也同样会回到英雄列表页。 在 Angular 应用中导航也会和标准的 Web 导航一样更新浏览器中的历史。</p><p translation-origin="off">Had you clicked the browser's back button instead of the "Back" button, the app would have returned you to the heroes list as well. Angular app navigation updates the browser history as normal web navigation does.</p><p translation-result="on">现在，点击<em>危机中心</em>链接，前往<em>危机</em>列表页。</p><p translation-origin="off">Now click the <em>Crisis Center</em> link for a list of ongoing crises.</p><div class="lightbox"><img src="generated/images/guide/router/crisis-center-list.png" alt="Crisis Center List" width="250" height="209"></div><p translation-result="on">选择其中之一，该应用就会把你带到此危机的编辑页面。 <em>危机详情</em>是当前页的子组件，就在列表的紧下方。</p><p translation-origin="off">Select a crisis and the application takes you to a crisis editing screen. The <em>Crisis Detail</em> appears in a child component on the same page, beneath the list.</p><p translation-result="on">修改危机的名称。 注意，危机列表中的相应名称<strong>并没有</strong>修改。</p><p translation-origin="off">Alter the name of a crisis. Notice that the corresponding name in the crisis list does <em>not</em> change.</p><div class="lightbox"><img src="generated/images/guide/router/crisis-center-detail.png" alt="Crisis Center Detail" width="250" height="281"></div><p translation-result="on">这和<em>英雄详情</em>页略有不同。<em>英雄详情</em>会立即保存你所做的更改。 而<em>危机详情</em>页中，你的更改都是临时的 —— 除非按“保存”按钮保存它们，或者按“取消”按钮放弃它们。 这两个按钮都会导航回<em>危机中心</em>，显示危机列表。</p><p translation-origin="off">Unlike <em>Hero Detail</em>, which updates as you type, <em>Crisis Detail</em> changes are temporary until you either save or discard them by pressing the "Save" or "Cancel" buttons. Both buttons navigate back to the <em>Crisis Center</em> and its list of crises.</p><p translation-result="on"><strong><em>先不要点击这些按钮</em></strong>。 而是点击浏览器的后退按钮，或者点击“Heroes”链接。</p><p translation-origin="off"><strong><em>Do not click either button yet</em></strong>. Click the browser back button or the "Heroes" link instead.</p><p translation-result="on">这时会弹出一个对话框。</p><p translation-origin="off">Up pops a dialog box.</p><div class="lightbox"><img src="generated/images/guide/router/confirm-dialog.png" alt="Confirm Dialog" width="250" height="101"></div><p translation-result="on">你可以回答“确定”以放弃这些更改，或者回答“取消”来继续编辑。</p><p translation-origin="off">You can say "OK" and lose your changes or click "Cancel" and continue editing.</p><p translation-result="on">这种行为的幕后是路由器的 <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> 守卫。 该守卫让你有机会进行清理工作或在离开当前视图之前请求用户的许可。</p><p translation-origin="off">Behind this behavior is the router's <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> guard. The guard gives you a chance to clean-up or ask the user's permission before navigating away from the current view.</p><p translation-result="on"><code>Admin</code> 和 <code>Login</code> 按钮用于演示路由器的其它能力，本章稍后的部分会讲解它们。这里只是个简短的讲解。</p><p translation-origin="off">The <code>Admin</code> and <code>Login</code> buttons illustrate other router capabilities to be covered later in the guide. This short introduction will do for now.</p><p translation-result="on">这就开始本应用的第一个里程碑。</p><p translation-origin="off">Proceed to the first application milestone.</p><a id="getting-started"></a><h2 id="milestone-1-getting-started" translation-result="on">里程碑 1：起步<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-1-getting-started"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-1-getting-started">Milestone 1: Getting started<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-1-getting-started"><i class="material-icons">link</i></a></h2><p translation-result="on">开始本应用的一个简版，它在两个空路由之间导航。</p><p translation-origin="off">Begin with a simple version of the app that navigates between two empty views.</p><div class="lightbox"><img src="generated/images/guide/router/router-1-anim.gif" alt="App in action" width="250" height="152"></div><a id="import"></a><p translation-result="on">遵循这些步骤生成一个范例应用。</p><p translation-origin="off">Generate a sample application to follow the walkthrough.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng new angular-router-sample</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng </span><span class="kwd">new</span><span class="pln"> angular</span><span class="pun">-</span><span class="pln">router</span><span class="pun">-</span><span class="pln">sample</span></code>
    </pre></aio-code></code-example><h3 id="define-routes" translation-result="on">定义路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#define-routes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="define-routes">Define Routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#define-routes"><i class="material-icons">link</i></a></h3><p translation-result="on">路由器必须用“路由定义”的列表进行配置。</p><p translation-origin="off">A router must be configured with a list of route definitions.</p><p translation-result="on">每个定义都被翻译成了一个<a href="api/router/Route">Route</a>对象。该对象有一个 <code>path</code> 字段，表示该路由中的 URL 路径部分，和一个 <code>component</code> 字段，表示与该路由相关联的组件。</p><p translation-origin="off">Each definition translates to a <a href="api/router/Route">Route</a> object which has two things: a <code>path</code>, the URL path segment for this route; and a <code>component</code>, the component associated with this route.</p><p translation-result="on">当浏览器的 URL 变化时或在代码中告诉路由器导航到一个路径时，路由器就会翻出它用来保存这些路由定义的注册表。</p><p translation-origin="off">The router draws upon its registry of definitions when the browser URL changes or when application code tells the router to navigate along a route path.</p><p translation-result="on">直白的说，你可以这样解释第一个路由：</p><p translation-origin="off">In simpler terms, you might say this of the first route:</p><ul><li><p translation-result="on">当浏览器地址栏的 URL 变化时，如果它匹配上了路径部分 <code>/crisis-center</code>，路由器就会激活一个 <code>CrisisListComponent</code> 的实例，并显示它的视图。</p><p translation-origin="off">When the browser's location URL changes to match the path segment <code>/crisis-center</code>, then the router activates an instance of the <code>CrisisListComponent</code> and displays its view.</p></li><li><p translation-result="on"><strong>当应用程序请求导航到路径 <code>/crisis-center</code> 时，路由器激活一个 <code>CrisisListComponent</code> 的实例，显示它的视图，并将该路径更新到浏览器地址栏和历史。</strong></p><p translation-origin="off">When the application requests navigation to the path <code>/crisis-center</code>, the router activates an instance of <code>CrisisListComponent</code>, displays its view, and updates the browser's address location and history with the URL for that path.</p></li></ul><p translation-result="on">第一个配置定义了由两个路由构成的数组，它们用简单的路径指向了 <code>CrisisListComponent</code> 和 <code>HeroListComponent</code>。来生成 <code>CrisisList</code> 和 <code>HeroList</code>。</p><p translation-origin="off">The first configuration defines an array of two routes with simple paths leading to the <code>CrisisListComponent</code> and <code>HeroListComponent</code>. Generate the <code>CrisisList</code> and <code>HeroList</code> components.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component crisis-list</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component crisis</span><span class="pun">-</span><span class="pln">list</span></code>
    </pre></aio-code></code-example><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component hero-list</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component hero</span><span class="pun">-</span><span class="pln">list</span></code>
    </pre></aio-code></code-example><p translation-result="on">把每个组件的内容都替换成下列范例 HTML。</p><p translation-origin="off">Replace the contents of each component with the sample HTML below.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="src/app/crisis-list/crisis-list.component.html" path="router/src/app/crisis-list/crisis-list.component.1.html">&lt;h2&gt;CRISIS CENTER&lt;/h2&gt; &lt;p&gt;Get your crisis here&lt;/p&gt;</code-pane><code-pane header="src/app/hero-list/hero-list.component.html" path="router/src/app/hero-list/hero-list.component.1.html" region="template">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;p&gt;Get your heroes here&lt;/p&gt;</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-0-0" tabindex="0" aria-posinset="1" aria-setsize="2" aria-controls="mat-tab-content-0-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/crisis-list/crisis-list.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-0-1" tabindex="-1" aria-posinset="2" aria-setsize="2" aria-controls="mat-tab-content-0-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/hero-list/hero-list.component.html</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:313px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-2 mat-tab-body-active ng-star-inserted" id="mat-tab-content-0-0" aria-labelledby="mat-tab-label-0-0"><div class="mat-tab-body-content ng-tns-c50-2 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-list/crisis-list.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h2&gt;</span><span class="pln">CRISIS CENTER</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
</span><span class="tag">&lt;p&gt;</span><span class="pln">Get your crisis here</span><span class="tag">&lt;/p&gt;</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-3 ng-star-inserted" id="mat-tab-content-0-1" aria-labelledby="mat-tab-label-0-1"><div class="mat-tab-body-content ng-tns-c50-3 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><h3 id="register-router-and-routes" translation-result="on">注册路由器与路由定义<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#register-router-and-routes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="register-router-and-routes">Register Router and Routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#register-router-and-routes"><i class="material-icons">link</i></a></h3><p translation-result="on">要使用路由器，必须先注册来自 <code>@angular/router</code> 包中的 <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code>。 定义一个路由数组 <code>appRoutes</code> 并把它传给 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 方法。 它会返回一个模块，其中包含配置好的 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务提供者，以及路由库所需的其它提供者。 一旦启动了应用，<code><a href="api/router/Router" class="code-anchor">Router</a></code> 就会根据当前的浏览器 URL 进行首次导航。</p><p translation-origin="off">In order to use the Router, you must first register the <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> from the <code>@angular/router</code> package. Define an array of routes, <code>appRoutes</code>, and pass them to the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> method. It returns a module, containing the configured <code><a href="api/router/Router" class="code-anchor">Router</a></code> service provider, plus other providers that the routing library requires. Once the application is bootstrapped, the <code><a href="api/router/Router" class="code-anchor">Router</a></code> performs the initial navigation based on the current browser URL.</p><div class="alert is-important"><p translation-result="on"><strong>注意：</strong> <code>RouterModule.forRoot</code> 方法是用于注册全应用级提供者的编码模式。要详细了解全应用级提供者，参见<a href="guide/singleton-services#forRoot-router">单例服务</a> 一章。</p><p translation-origin="off"><strong>Note:</strong> The <code>RouterModule.forRoot</code> method is a pattern used to register application-wide providers. Read more about application-wide providers in the <a href="guide/singleton-services#forRoot-router">Singleton services</a> guide.</p></div><code-example path="router/src/app/app.module.1.ts" header="src/app/app.module.ts (first-config)" region="first-config" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { AppComponent } from './app.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { HeroListComponent } from './hero-list/hero-list.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent }, ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], declarations: [ AppComponent, HeroListComponent, CrisisListComponent, ], bootstrap: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts (first-config)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (first-config)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">        </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">          </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">          </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">作为简单的路由配置，将添加配置好的 <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> 到 <code>AppModule</code> 中就足够了。 随着应用的成长，你将需要<a href="guide/router#refactor-the-routing-configuration-into-a-routing-module">将路由配置重构</a>到单独的文件中，并创建<strong><a href="guide/router#routing-module">路由模块</a></strong> - 一种特别的、专门为特性模块的路由器服务的<strong>服务模块</strong>。</p><p translation-origin="off">Adding the configured <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> to the <code>AppModule</code> is sufficient for simple route configurations. As the application grows, you'll want to <a href="guide/router#refactor-the-routing-configuration-into-a-routing-module">refactor the routing configuration</a> into a separate file and create a <strong><a href="guide/router#routing-module">Routing Module</a></strong>, a special type of <code>Service Module</code> dedicated to the purpose of routing in feature modules.</p></div><p translation-result="on">把 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 注册到 <code>AppModule</code> 的 <code>imports</code> 中，能让该 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务在应用的任何地方都能使用。</p><p translation-origin="off">Registering the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> in the <code>AppModule</code> imports makes the <code><a href="api/router/Router" class="code-anchor">Router</a></code> service available everywhere in the application.</p><a id="shell"></a><h3 id="add-the-router-outlet" translation-result="on">添加路由出口<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-the-router-outlet"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="add-the-router-outlet">Add the Router Outlet<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-the-router-outlet"><i class="material-icons">link</i></a></h3><p translation-result="on">根组件 <code>AppComponent</code> 是本应用的壳。它在顶部有一个标题、一个带两个链接的导航条，在底部有一个<em>路由器出口</em>，路由器会在它所指定的位置上把组件切入或调出页面。就像下图中所标出的：</p><p translation-origin="off">The root <code>AppComponent</code> is the application shell. It has a title, a navigation bar with two links, and a router outlet where the router swaps components on and off the page. Here's what you get:</p><div class="lightbox"><img src="generated/images/guide/router/shell-and-outlet.png" alt="Shell" width="300" height="102"></div><p translation-result="on">路由出口扮演一个占位符的角色，路由组件将会渲染在它的下方。</p><p translation-origin="off">The router outlet serves as a placeholder when the routed components will be rendered below it.</p><a id="shell-template"></a><p translation-result="on">该组件所对应的模板是这样的：</p><p translation-origin="off">The corresponding component template looks like this:</p><code-example path="router/src/app/app.component.1.html" header="src/app/app.component.html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h1&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;/nav&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/app.component.html</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><a id="wildcard"></a><h3 id="define-a-wildcard-route" translation-result="on">定义通配符路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#define-a-wildcard-route"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="define-a-wildcard-route">Define a Wildcard route<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#define-a-wildcard-route"><i class="material-icons">link</i></a></h3><p translation-result="on">你以前在应用中创建过两个路由，一个是 <code>/crisis-center</code>，另一个是 <code>/heroes</code>。 所有其它 URL 都会导致路由器抛出错误，并让应用崩溃。</p><p translation-origin="off">You've created two routes in the app so far, one to <code>/crisis-center</code> and the other to <code>/heroes</code>. Any other URL causes the router to throw an error and crash the app.</p><p translation-result="on">可以添加一个<strong>通配符</strong>路由来拦截所有无效的 URL，并优雅的处理它们。 <em>通配符</em>路由的 <code>path</code> 是两个星号（<code>**</code>），它会匹配<em>任何</em> URL。 当路由器匹配不上以前定义的那些路由时，它就会选择<em>这个</em>路由。 通配符路由可以导航到自定义的“404 Not Found”组件，也可以<a href="guide/router#redirect">重定向</a>到一个现有路由。</p><p translation-origin="off">Add a <strong>wildcard</strong> route to intercept invalid URLs and handle them gracefully. A <em>wildcard</em> route has a path consisting of two asterisks. It matches <em>every</em> URL. The router will select <em>this</em> route if it can't match a route earlier in the configuration. A wildcard route can navigate to a custom "404 Not Found" component or <a href="guide/router#redirect">redirect</a> to an existing route.</p><div class="alert is-helpful"><p translation-result="on">路由器使用<a href="guide/router#example-config">先匹配者优先</a>的策略来选择路由。 通配符路由是路由配置中最没有特定性的那个，因此务必确保它是配置中的<em>最后一个</em>路由。</p><p translation-origin="off">The router selects the route with a <a href="guide/router#example-config"><em>first match wins</em></a> strategy. Wildcard routes are the least specific routes in the route configuration. Be sure it is the <em>last</em> route in the configuration.</p></div><p translation-result="on">要测试本特性，请往 <code>HeroListComponent</code> 的模板中添加一个带 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 的按钮，并且把它的链接设置为 <code>"/sidekicks"</code>。</p><p translation-origin="off">To test this feature, add a button with a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> to the <code>HeroListComponent</code> template and set the link to <code>"/sidekicks"</code>.</p><code-example path="router/src/app/hero-list/hero-list.component.1.html" header="src/app/hero-list/hero-list.component.html (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;p&gt;Get your heroes here&lt;/p&gt; &lt;button <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/sidekicks"&gt;Go to sidekicks&lt;/button&gt;</div><header class="ng-star-inserted">src/app/hero-list/hero-list.component.html (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/hero-list/hero-list.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h2&gt;</span><span class="pln">HEROES</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
</span><span class="tag">&lt;p&gt;</span><span class="pln">Get your heroes here</span><span class="tag">&lt;/p&gt;</span><span class="pln">

</span><span class="tag">&lt;button</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/sidekicks"</span><span class="tag">&gt;</span><span class="pln">Go to sidekicks</span><span class="tag">&lt;/button&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">当用户点击该按钮时，应用就会失败，因为你尚未定义过 <code>"/sidekicks"</code> 路由。</p><p translation-origin="off">The application will fail if the user clicks that button because you haven't defined a <code>"/sidekicks"</code> route yet.</p><p translation-result="on">不要添加 <code>"/sidekicks"</code> 路由，而是定义一个“通配符”路由，让它直接导航到 <code>PageNotFoundComponent</code> 组件。</p><p translation-origin="off">Instead of adding the <code>"/sidekicks"</code> route, define a <code>wildcard</code> route instead and have it navigate to a simple <code>PageNotFoundComponent</code>.</p><code-example path="router/src/app/app.module.1.ts" header="src/app/app.module.ts (wildcard)" region="wildcard" ng-version="9.0.0-rc.11"><div style="display:none">{ path: '**', component: PageNotFoundComponent }</div><header class="ng-star-inserted">src/app/app.module.ts (wildcard)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (wildcard)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">创建 <code>PageNotFoundComponent</code>，以便在用户访问无效网址时显示它。</p><p translation-origin="off">Create the <code>PageNotFoundComponent</code> to display when users visit invalid URLs.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component page-not-found</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component page</span><span class="pun">-</span><span class="kwd">not</span><span class="pun">-</span><span class="pln">found</span></code>
    </pre></aio-code></code-example><code-example path="router/src/app/page-not-found/page-not-found.component.html" header="src/app/page-not-found.component.html (404 component)" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h2&gt;Page not found&lt;/h2&gt;</div><header class="ng-star-inserted">src/app/page-not-found.component.html (404 component)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/page-not-found.component.html (404 component)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h2&gt;</span><span class="pln">Page not found</span><span class="tag">&lt;/h2&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">现在，当用户访问 <code>/sidekicks</code> 或任何无效的 URL 时，浏览器就会显示“Page not found”。 浏览器的地址栏仍指向无效的 URL。</p><p translation-origin="off">Now when the user visits <code>/sidekicks</code>, or any other invalid URL, the browser displays "Page not found". The browser address bar continues to point to the invalid URL.</p><a id="redirect"></a><h3 id="set-up-redirects" translation-result="on">设置跳转<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#set-up-redirects"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="set-up-redirects">Set up redirects<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#set-up-redirects"><i class="material-icons">link</i></a></h3><p translation-result="on">应用启动时，浏览器地址栏中的初始 URL 是这样的：</p><p translation-origin="off">When the application launches, the initial URL in the browser bar is something like:</p><code-example ng-version="9.0.0-rc.11"><div style="display:none">localhost:4200</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">4200</span></code>
    </pre></aio-code></code-example><p translation-result="on">它不能匹配上任何具体的路由，于是就会走到通配符路由中去，并且显示 <code>PageNotFoundComponent</code>。</p><p translation-origin="off">That doesn't match any of the concrete configured routes which means the router falls through to the wildcard route and displays the <code>PageNotFoundComponent</code>.</p><p translation-result="on">这个应用需要一个有效的<strong>默认路由</strong>，在这里应该用英雄列表作为默认页。当用户点击"Heroes"链接或把 <code>localhost:4200/heroes</code> 粘贴到地址栏时，它应该导航到列表页。</p><p translation-origin="off">The application needs a <strong>default route</strong> to a valid page. The default page for this app is the list of heroes. The app should navigate there as if the user clicked the "Heroes" link or pasted <code>localhost:4200/heroes</code> into the address bar.</p><p translation-result="on">首选方案是添加一个 <code>redirect</code> 路由来把最初的相对路径（<code>''</code>）转换成期望的默认路径（<code>/heroes</code>）。 浏览器地址栏会显示 <code>.../heroes</code>，就像你直接导航到那里一样。</p><p translation-origin="off">The preferred solution is to add a <code>redirect</code> route that translates the initial relative URL (<code>''</code>) to the desired default path (<code>/heroes</code>). The browser address bar shows <code>.../heroes</code> as if you'd navigated there directly.</p><p translation-result="on">在通配符路由<em>上方</em>添加一个默认路由。 在下方的代码片段中，它出现在通配符路由的紧上方，展示了这个里程碑的完整 <code>appRoutes</code>。</p><p translation-origin="off">Add the default route somewhere <em>above</em> the wildcard route. It's just above the wildcard route in the following excerpt showing the complete <code>appRoutes</code> for this milestone.</p><code-example path="router/src/app/app-routing.module.1.ts" header="src/app/app-routing.module.ts (appRoutes)" region="appRoutes" ng-version="9.0.0-rc.11"><div style="display:none">const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ];</div><header class="ng-star-inserted">src/app/app-routing.module.ts (appRoutes)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (appRoutes)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln">        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">   </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span></code>
    </pre></aio-code></code-example><p translation-result="on">重定向路由需要一个 <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> 属性，来告诉路由器如何用 URL 去匹配路由的路径，否则路由器就会报错。 在本应用中，路由器应该只有在<em>完整的 URL</em>等于 <code>''</code> 时才选择 <code>HeroListComponent</code> 组件，因此要把 <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> 设置为 <code>'<a href="api/core/Version#full" class="code-anchor">full</a>'</code>。</p><p translation-origin="off">A redirect route requires a <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> property to tell the router how to match a URL to the path of a route. The router throws an error if you don't. In this app, the router should select the route to the <code>HeroListComponent</code> only when the <em>entire URL</em> matches <code>''</code>, so set the <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> value to <code>'<a href="api/core/Version#full" class="code-anchor">full</a>'</code>.</p><div class="alert is-helpful"><p translation-result="on">从技术角度说，<code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a> = '<a href="api/core/Version#full" class="code-anchor">full</a>'</code> 导致 URL 中<em>剩下的</em>、未匹配的部分必须等于 <code>''</code>。 在这个例子中，跳转路由在一个顶层路由中，因此<em>剩下的</em>URL 和<em>完整的</em>URL 是一样的。</p><p translation-origin="off">Technically, <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a> = '<a href="api/core/Version#full" class="code-anchor">full</a>'</code> results in a route hit when the <em>remaining</em>, unmatched segments of the URL match <code>''</code>. In this example, the redirect is in a top level route so the <em>remaining</em> URL and the <em>entire</em> URL are the same thing.</p><p translation-result="on"><code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> 的另一个可能的值是 <code>'prefix'</code>，它会告诉路由器：当<em>剩下的</em>URL 以这个跳转路由中的 <code>prefix</code> 值开头时，就会匹配上这个跳转路由。</p><p translation-origin="off">The other possible <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> value is <code>'prefix'</code> which tells the router to match the redirect route when the <em>remaining</em> URL <strong><em>begins</em></strong> with the redirect route's <em>prefix</em> path.</p><p translation-result="on">在这里不能这么做！如果 <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> 的值是 <code>'prefix'</code>，那么<em>每个</em>URL 都会匹配上 <code>''</code>。</p><p translation-origin="off">Don't do that here. If the <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a></code> value were <code>'prefix'</code>, <em>every</em> URL would match <code>''</code>.</p><p translation-result="on">尝试把它设置为 <code>'prefix'</code>，然后点击 <code>Go to sidekicks</code> 按钮。别忘了，它是一个无效 URL，本应显示“Page not found”页。 但是，你仍然在“英雄列表”页中。在地址栏中输入一个无效的 URL，你又被路由到了 <code>/heroes</code>。 <em>每一个</em> URL，无论有效与否，都会匹配上这个路由定义。</p><p translation-origin="off">Try setting it to <code>'prefix'</code> then click the <code>Go to sidekicks</code> button. Remember that's a bad URL and you should see the "Page not found" page. Instead, you're still on the "Heroes" page. Enter a bad URL in the browser address bar. You're instantly re-routed to <code>/heroes</code>. <em>Every</em> URL, good or bad, that falls through to <em>this</em> route definition will be a match.</p><p translation-result="on">默认路由应该只有在<em>整个</em>URL 等于 <code>''</code> 时才重定向到 <code>HeroListComponent</code>，别忘了把重定向路由设置为 <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a> = '<a href="api/core/Version#full" class="code-anchor">full</a>'</code>。</p><p translation-origin="off">The default route should redirect to the <code>HeroListComponent</code> <em>only</em> when the <em>entire</em> url is <code>''</code>. Remember to restore the redirect to <code><a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a> = '<a href="api/core/Version#full" class="code-anchor">full</a>'</code>.</p><p translation-result="on">要了解更多，参见 Victor Savkin 的帖子<a href="http://victorsavkin.com/post/146722301646/angular-router-empty-paths-componentless-routes">关于重定向</a>。</p><p translation-origin="off">Learn more in Victor Savkin's <a href="http://vsavkin.tumblr.com/post/146722301646/angular-router-empty-paths-componentless-routes">post on redirects</a>.</p></div><h3 id="basics-wrap-up" translation-result="on">“起步阶段”总结<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#basics-wrap-up"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="basics-wrap-up">Basics wrap up<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#basics-wrap-up"><i class="material-icons">link</i></a></h3><p translation-result="on">你得到了一个非常基本的、带导航的应用，当用户点击链接时，它能在两个视图之间切换。</p><p translation-origin="off">You've got a very basic navigating app, one that can switch between two views when the user clicks a link.</p><p translation-result="on">你学到了如何：</p><p translation-origin="off">You've learned how to do the following:</p><ul><li><p translation-result="on">加载路由库</p><p translation-origin="off">Load the router library.</p></li><li><p translation-result="on">往壳组件的模板中添加一个导航条，导航条中有一些 A 标签、<code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> 指令和 <code><a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a></code> 指令</p><p translation-origin="off">Add a nav bar to the shell template with anchor tags, <code><a href="api/router/RouterLink" class="code-anchor">routerLink</a></code> and <code><a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a></code> directives.</p></li><li><p translation-result="on">往壳组件的模板中添加一个 <code><a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a></code> 指令，视图将会被显示在那里</p><p translation-origin="off">Add a <code><a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a></code> to the shell template where views will be displayed.</p></li><li><p translation-result="on">用 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 配置路由器模块</p><p translation-origin="off">Configure the router module with <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code>.</p></li><li><p translation-result="on">设置路由器，使其合成 HTML5 模式的浏览器 URL</p><p translation-origin="off">Set the router to compose HTML5 browser URLs.</p></li><li><p translation-result="on">使用通配符路由来处理无效路由</p><p translation-origin="off">handle invalid routes with a <code>wildcard</code> route.</p></li><li><p translation-result="on">当应用在空路径下启动时，导航到默认路由</p><p translation-origin="off">navigate to the default route when the app launches with an empty path.</p></li></ul><p translation-result="on">这个初学者应用的结构是这样的：</p><p translation-origin="off">The starter app's structure looks like this:</p><div class="filetree"><div class="file"><p>angular-router-sample</p></div><div class="children"><div class="file"><p>src</p></div><div class="children"><div class="file"><p>app</p></div><div class="children"><div class="file"><p>crisis-list</p></div><div class="children"><div class="file"><p>crisis-list.component.css</p></div><div class="file"><p>crisis-list.component.html</p></div><div class="file"><p>crisis-list.component.ts</p></div></div><div class="file"><p>hero-list</p></div><div class="children"><div class="file"><p>hero-list.component.css</p></div><div class="file"><p>hero-list.component.html</p></div><div class="file"><p>hero-list.component.ts</p></div></div><div class="file">page-not-found</div><div class="children"><div class="file"><p>page-not-found.component.css</p></div><div class="file"><p>page-not-found.component.html</p></div><div class="file"><p>page-not-found.component.ts</p></div></div><div class="file">app.component.css</div><div class="file">app.component.html</div><div class="file">app.component.ts</div><div class="file"><p>app.module.ts</p></div></div><div class="file"><p>main.ts</p></div><div class="file"><p>index.html</p></div><div class="file"><p>styles.css</p></div><div class="file"><p>tsconfig.json</p></div></div><div class="file"><p>node_modules ...</p></div><div class="file"><p>package.json</p></div></div></div><p translation-result="on">下面是当前里程碑中讨论过的文件列表：</p><p translation-origin="off">Here are the files discussed in this milestone.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="app.component.html" path="router/src/app/app.component.1.html">&lt;h1&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;/nav&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code-pane><code-pane header="app.module.ts" path="router/src/app/app.module.1.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { AppComponent } from './app.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { HeroListComponent } from './hero-list/hero-list.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], declarations: [ AppComponent, HeroListComponent, CrisisListComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</code-pane><code-pane header="hero-list/hero-list.component.html" path="router/src/app/hero-list/hero-list.component.1.html">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;p&gt;Get your heroes here&lt;/p&gt; &lt;button <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/sidekicks"&gt;Go to sidekicks&lt;/button&gt;</code-pane><code-pane header="crisis-list/crisis-list.component.html" path="router/src/app/crisis-list/crisis-list.component.1.html">&lt;h2&gt;CRISIS CENTER&lt;/h2&gt; &lt;p&gt;Get your crisis here&lt;/p&gt;</code-pane><code-pane header="page-not-found/page-not-found.component.html" path="router/src/app/page-not-found/page-not-found.component.html">&lt;h2&gt;Page not found&lt;/h2&gt;</code-pane><code-pane header="index.html" path="router/src/index.html">&lt;html lang="en"&gt; &lt;head&gt; &lt;!-- Set the base href --&gt; &lt;base href="/"&gt; &lt;title&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/title&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt; &lt;/head&gt; &lt;body&gt; &lt;app-root&gt;&lt;/app-root&gt; &lt;/body&gt; &lt;/html&gt;</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-1-0" tabindex="0" aria-posinset="1" aria-setsize="6" aria-controls="mat-tab-content-1-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-1-1" tabindex="-1" aria-posinset="2" aria-setsize="6" aria-controls="mat-tab-content-1-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-1-2" tabindex="-1" aria-posinset="3" aria-setsize="6" aria-controls="mat-tab-content-1-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-list/hero-list.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-1-3" tabindex="-1" aria-posinset="4" aria-setsize="6" aria-controls="mat-tab-content-1-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-list/crisis-list.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-1-4" tabindex="-1" aria-posinset="5" aria-setsize="6" aria-controls="mat-tab-content-1-4" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">page-not-found/page-not-found.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-1-5" tabindex="-1" aria-posinset="6" aria-setsize="6" aria-controls="mat-tab-content-1-5" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">index.html</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:175px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-4 mat-tab-body-active ng-star-inserted" id="mat-tab-content-1-0" aria-labelledby="mat-tab-label-1-0"><div class="mat-tab-body-content ng-tns-c50-4 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from app.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-5 ng-star-inserted" id="mat-tab-content-1-1" aria-labelledby="mat-tab-label-1-1"><div class="mat-tab-body-content ng-tns-c50-5 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-6 ng-star-inserted" id="mat-tab-content-1-2" aria-labelledby="mat-tab-label-1-2"><div class="mat-tab-body-content ng-tns-c50-6 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-7 ng-star-inserted" id="mat-tab-content-1-3" aria-labelledby="mat-tab-label-1-3"><div class="mat-tab-body-content ng-tns-c50-7 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-8 ng-star-inserted" id="mat-tab-content-1-4" aria-labelledby="mat-tab-label-1-4"><div class="mat-tab-body-content ng-tns-c50-8 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-9 ng-star-inserted" id="mat-tab-content-1-5" aria-labelledby="mat-tab-label-1-5"><div class="mat-tab-body-content ng-tns-c50-9 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><a id="routing-module"></a><h2 id="milestone-2-routing-module" translation-result="on">里程碑 2：<strong>路由模块</strong><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-2-routing-module"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-2-routing-module">Milestone 2: <em>Routing module</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-2-routing-module"><i class="material-icons">link</i></a></h2><p translation-result="on">在原始的路由配置中，你提供了仅有两个路由的简单配置来设置应用的路由。对于简单的路由，这没有问题。 随着应用的成长，你用到了更多<strong>路由器</strong>特性，比如守卫、解析器和子路由等，你会很自然地想要重构路由。 我们建议将路由信息移到一个单独的特殊用途的模块，叫做<strong>路由模块</strong>。</p><p translation-origin="off">In the initial route configuration, you provided a simple setup with two routes used to configure the application for routing. This is perfectly fine for simple routing. As the application grows and you make use of more <code><a href="api/router/Router" class="code-anchor">Router</a></code> features, such as guards, resolvers, and child routing, you'll naturally want to refactor the routing configuration into its own file. We recommend moving the routing information into a special-purpose module called a <em>Routing Module</em>.</p><p translation-result="on"><strong>路由模块</strong>有一系列特性：</p><p translation-origin="off">The <strong>Routing Module</strong> has several characteristics:</p><ul><li><p translation-result="on">把路由这个关注点从其它应用类关注点中分离出去。</p><p translation-origin="off">Separates routing concerns from other application concerns.</p></li><li><p translation-result="on">测试特性模块时，可以替换或移除路由模块。</p><p translation-origin="off">Provides a module to replace or remove when testing the application.</p></li><li><p translation-result="on">为路由服务提供者（包括守卫和解析器等）提供一个共同的地方。</p><p translation-origin="off">Provides a well-known location for routing service providers including guards and resolvers.</p></li><li><p translation-result="on"><strong>不要</strong>声明组件。</p><p translation-origin="off">Does <strong>not</strong> declare components.</p></li></ul><a id="integrate-routing"></a><h3 id="integrate-routing-with-your-app" translation-result="on">把路由集成到应用中<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#integrate-routing-with-your-app"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="integrate-routing-with-your-app">Integrate routing with your app<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#integrate-routing-with-your-app"><i class="material-icons">link</i></a></h3><p translation-result="on">路由应用范例中默认不包含路由。 要想在使用 <a href="cli">Angular CLI</a> 创建项目时支持路由，请为项目或应用的每个 NgModule 设置 <code>--routing</code> 选项。 当你用 CLI 命令 <a href="cli/new"><code>ng new</code></a>创建新项目或用 <a href="cli/generate"><code>ng generate app</code></a>命令创建新应用，请指定 <code>--routing</code> 选项。这会告诉 CLI 包含上 <code>@angular/router</code> 包，并创建一个名叫 <code>app-routing.module.ts</code> 的文件。 然后你就可以在添加到项目或应用中的任何 NgModule 中使用路由功能了。</p><p translation-origin="off">The sample routing application does not include routing by default. When you use the <a href="cli">Angular CLI</a> to create a project that will use routing, set the <code>--routing</code> option for the project or app, and for each NgModule. When you create or initialize a new project (using the CLI <a href="cli/new"><code>ng new</code></a>command) or a new app (using the <a href="cli/generate"><code>ng generate app</code></a>command), specify the <code>--routing</code> option. This tells the CLI to include the <code>@angular/router</code> npm package and create a file named <code>app-routing.module.ts</code>. You can then use routing in any NgModule that you add to the project or app.</p><p translation-result="on">比如，可以用下列命令生成带路由的 NgModule。</p><p translation-origin="off">For example, the following command generates an NgModule that can use routing.</p><code-example language="sh" ng-version="9.0.0-rc.11"><div style="display:none">ng generate module my-module --routing</div><aio-code><pre class="lang-sh prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate module my</span><span class="pun">-</span><span class="pln">module </span><span class="pun">--</span><span class="pln">routing</span></code>
    </pre></aio-code></code-example><p translation-result="on">这将创建一个名叫 <code>my-module-routing.module.ts</code> 的独立文件，来保存这个 NgModule 的路由信息。 该文件包含一个空的 <code><a href="api/router/Routes" class="code-anchor">Routes</a></code> 对象，你可以使用一些指向各个组件和 NgModule 的路由来填充该对象。</p><p translation-origin="off">This creates a separate file named <code>my-module-routing.module.ts</code> to store the NgModule's routes. The file includes an empty <code><a href="api/router/Routes" class="code-anchor">Routes</a></code> object that you can fill with routes to different components and NgModules.</p><a id="routing-refactor"></a><h3 id="refactor-the-routing-configuration-into-a-routing-module" translation-result="on">将路由配置重构为<em>路由模块</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#refactor-the-routing-configuration-into-a-routing-module"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="refactor-the-routing-configuration-into-a-routing-module">Refactor the routing configuration into a <em>routing module</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#refactor-the-routing-configuration-into-a-routing-module"><i class="material-icons">link</i></a></h3><p translation-result="on">在 <code>/app</code> 目录下创建一个 <code>AppRouting</code> 模块，以包含路由配置。</p><p translation-origin="off">Create an <code>AppRouting</code> module in the <code>/app</code> folder to contain the routing configuration.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate module app-routing --module app --flat</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate </span><span class="kwd">module</span><span class="pln"> app</span><span class="pun">-</span><span class="pln">routing </span><span class="pun">--</span><span class="kwd">module</span><span class="pln"> app </span><span class="pun">--</span><span class="pln">flat</span></code>
    </pre></aio-code></code-example><p translation-result="on">导入 <code>CrisisListComponent</code>、<code>HeroListComponent</code> 和 <code>PageNotFoundCompponent</code> 组件，就像 <code>app.module.ts</code> 中那样。然后把 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 的导入语句和路由配置以及 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 移入这个路由模块中。</p><p translation-origin="off">Import the <code>CrisisListComponent</code>, <code>HeroListComponent</code>, and <code>PageNotFoundComponent</code> symbols just like you did in the <code>app.module.ts</code>. Then move the <code><a href="api/router/Router" class="code-anchor">Router</a></code> imports and routing configuration, including <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code>, into this routing module.</p><p translation-result="on">把 Angular 的 <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code>添加到该模块的 <code>exports</code> 数组中，以便再次导出它 。 通过再次导出 <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code>，当在 <code>AppModule</code> 中导入了 <code>AppRoutingModule</code> 之后，那些声明在 <code>AppModule</code> 中的组件就可以访问路由指令了，比如 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 和 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>。</p><p translation-origin="off">Re-export the Angular <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> by adding it to the module <code>exports</code> array. By re-exporting the <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> here the components declared in <code>AppModule</code> will have access to router directives such as <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> and <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>.</p><p translation-result="on">做完这些之后，该文件变成了这样：</p><p translation-origin="off">After these steps, the file should look like this.</p><code-example path="router/src/app/app-routing.module.1.ts" header="src/app/app-routing.module.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { HeroListComponent } from './hero-list/hero-list.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule {}</div><header class="ng-star-inserted">src/app/app-routing.module.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">              </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln">        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">   </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><p translation-result="on">接下来，修改 <code>app.module.ts</code> 文件，从 <code>imports</code> 数组中移除 <code>RouterModule.forRoot</code>。</p><p translation-origin="off">Next, update the <code>app.module.ts</code> file, removing <code>RouterModule.forRoot</code> in the <code>imports</code> array.</p><code-example path="router/src/app/app.module.2.ts" header="src/app/app.module.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { HeroListComponent } from './hero-list/hero-list.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, AppRoutingModule ], declarations: [ AppComponent, HeroListComponent, CrisisListComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app-routing.module'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">AppRoutingModule</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">本章稍后的部分，你将创建一个<a href="guide/router#heroes-functionality">多路由模块</a>，并揭示你为何必须<a href="guide/router#routing-module-order">以正确的顺序导入那些路由模块</a>。</p><p translation-origin="off">Later in this guide you will create <a href="guide/router#heroes-functionality">multiple routing modules</a> and discover that you must import those routing modules <a href="guide/router#routing-module-order">in the correct order</a>.</p></div><p translation-result="on">应用继续照常运行，你可以把路由模块作为将来每个模块维护路由配置的中心位置。</p><p translation-origin="off">The application continues to work just the same, and you can use <code>AppRoutingModule</code> as the central place to maintain future routing configuration.</p><a id="why-routing-module"></a><h3 id="do-you-need-a-routing-module" translation-result="on">你需要<strong>路由模块</strong>吗？<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#do-you-need-a-routing-module"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="do-you-need-a-routing-module">Do you need a <em>Routing Module</em>?<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#do-you-need-a-routing-module"><i class="material-icons">link</i></a></h3><p translation-result="on"><strong>路由模块</strong>在根模块或者特性模块替换了路由配置。在路由模块或者在模块内部配置路由，但不要同时在两处都配置。</p><p translation-origin="off">The <em>Routing Module</em> <em>replaces</em> the routing configuration in the root or feature module. <em>Either</em> configure routes in the Routing Module <em>or</em> within the module itself but not in both.</p><p translation-result="on">路由模块是设计选择，它的价值在配置很复杂，并包含专门守卫和解析器服务时尤其明显。 在配置很简单时，它可能看起来很多余。</p><p translation-origin="off">The Routing Module is a design choice whose value is most obvious when the configuration is complex and includes specialized guard and resolver services. It can seem like overkill when the actual configuration is dead simple.</p><p translation-result="on">在配置很简单时，一些开发者跳过路由模块（例如 <code>AppRoutingModule</code>），并将路由配置直接混合在关联模块中（比如 <code>AppModule</code>&nbsp;）。</p><p translation-origin="off">Some developers skip the Routing Module (for example, <code>AppRoutingModule</code>) when the configuration is simple and merge the routing configuration directly into the companion module (for example, <code>AppModule</code>).</p><p translation-result="on">从中选择一种模式，并坚持模式的一致性。</p><p translation-origin="off">Choose one pattern or the other and follow that pattern consistently.</p><p translation-result="on">大多数开发者都应该采用路由模块，以保持一致性。 它在配置复杂时，能确保代码干净。 它让测试特性模块更加容易。 它的存在让人一眼就能看出这个模块是带路由的。 开发者可以很自然的从路由模块中查找和扩展路由配置。</p><p translation-origin="off">Most developers should always implement a Routing Module for the sake of consistency. It keeps the code clean when configuration becomes complex. It makes testing the feature module easier. Its existence calls attention to the fact that a module is routed. It is where developers expect to find and expand routing configuration.</p><a id="heroes-feature"></a><h2 id="milestone-3-heroes-feature" translation-result="on">里程碑 3: 英雄特征区<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-3-heroes-feature"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-3-heroes-feature">Milestone 3: Heroes feature<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-3-heroes-feature"><i class="material-icons">link</i></a></h2><p translation-result="on">你刚刚学习了如何用 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令进行导航。接下来要：</p><p translation-origin="off">You've seen how to navigate using the <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directive. Now you'll learn the following:</p><ul><li><p translation-result="on">用模块把应用和路由组织为一些<em>特性区</em></p><p translation-origin="off">Organize the app and routes into <em>feature areas</em> using modules.</p></li><li><p translation-result="on">命令式的从一个组件导航到另一个</p><p translation-origin="off">Navigate imperatively from one component to another.</p></li><li><p translation-result="on">通过路由传递必要信息和可选信息</p><p translation-origin="off">Pass required and optional information in route parameters.</p></li></ul><p translation-result="on">这个例子重写了<a href="tutorial/toh-pt4" title="Tour of Heroes: Services">《英雄指南》</a>的“服务”部分的英雄列表特性，你可以从<live-example name="toh-pt4" title="英雄指南：各个服务的范例代码" ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="英雄指南：各个服务的范例代码" href="generated/live-examples/toh-pt4/stackblitz.html">英雄指南：各个服务的范例代码</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/toh-pt4/toh-pt4.zip">下载范例</a></span></span></span></live-example>中复制大部分代码过来。</p><p translation-origin="off">This example recreates the heroes feature in the "Services" episode of the <a href="tutorial/toh-pt4" title="Tour of Heroes: Services">Tour of Heroes tutorial</a>, and you'll be copying much of the code from the<live-example name="toh-pt4" title="Tour of Heroes: Services example code" ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="Tour of Heroes: Services example code" href="generated/live-examples/toh-pt4/stackblitz.html">Tour of Heroes: Services example code</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/toh-pt4/toh-pt4.zip">下载范例</a></span></span></span></live-example>.</p><p translation-result="on">下面是用户将看到的版本：</p><p translation-origin="off">Here's how the user will experience this version of the app:</p><div class="lightbox"><img src="generated/images/guide/router/router-2-anim.gif" alt="App in action" width="400" height="475"></div><p translation-result="on">典型的应用具有多个<em>特性区</em>，每个特性区都专注于特定的业务用途。</p><p translation-origin="off">A typical application has multiple <em>feature areas</em>, each dedicated to a particular business purpose.</p><p translation-result="on">虽然你也可以把文件都放在 <code>src/app/</code> 目录下，但那样是不现实的，而且很难维护。 大部分开发人员更喜欢把每个特性区都放在它自己的目录下。</p><p translation-origin="off">While you could continue to add files to the <code>src/app/</code> folder, that is unrealistic and ultimately not maintainable. Most developers prefer to put each feature area in its own folder.</p><p translation-result="on">你准备把应用拆分成多个不同的<em>特性模块</em>，每个特有模块都有自己的关注点。 然后，你就会把它们导入到主模块中，并且在它们之间导航。</p><p translation-origin="off">You are about to break up the app into different <em>feature modules</em>, each with its own concerns. Then you'll import into the main module and navigate among them.</p><a id="heroes-functionality"></a><h3 id="add-heroes-functionality" translation-result="on">添加英雄管理功能<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-heroes-functionality"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="add-heroes-functionality">Add heroes functionality<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-heroes-functionality"><i class="material-icons">link</i></a></h3><p translation-result="on">遵循下列步骤：</p><p translation-origin="off">Follow these steps:</p><ul><li><p translation-result="on">在 <code>heroes</code> 目录下创建一个带路由的 <code>HeroesModule</code>，并把它注册进 <code>AppModule</code> 中。 这里就是你实现<em>英雄管理</em>特性的地方。</p><p translation-origin="off">Create a <code>HeroesModule</code> with routing in the heroes folder and register it with the root <code>AppModule</code>. This is where you'll be implementing the <em>hero management</em>.</p></li></ul><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate module heroes/heroes --module app --flat --routing</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate </span><span class="kwd">module</span><span class="pln"> heroes</span><span class="pun">/</span><span class="pln">heroes </span><span class="pun">--</span><span class="kwd">module</span><span class="pln"> app </span><span class="pun">--</span><span class="pln">flat </span><span class="pun">--</span><span class="pln">routing</span></code>
    </pre></aio-code></code-example><ul><li><p translation-result="on">把 <code>app</code> 下占位用的 <code>hero-list</code> 移到 <code>heroes</code> 目录中。</p><p translation-origin="off">Move the placeholder <code>hero-list</code> folder that's in the <code>app</code> into the <code>heroes</code> folder.</p></li><li><p translation-result="on">从<live-example name="toh-pt4" title="Tour of Heroes: Services example code" ng-version="9.0.0-rc.11"><span style="display:none">教程的 "服务" 部分</span><span><span class="ng-star-inserted"><a target="_blank" title="教程的 &quot;服务&quot; 部分" href="generated/live-examples/toh-pt4/stackblitz.html">教程的 "服务" 部分</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/toh-pt4/toh-pt4.zip">下载范例</a></span></span></span></live-example>把 <code>heroes/heroes.component.html</code> 的内容复制到 <code>hero-list.component.html</code> 模板中。</p><p translation-origin="off">Copy the contents of the <code>heroes/heroes.component.html</code> from the<live-example name="toh-pt4" title="Tour of Heroes: Services example code" ng-version="9.0.0-rc.11"><span style="display:none">"Services" tutorial</span><span><span class="ng-star-inserted"><a target="_blank" title="&quot;Services&quot; tutorial" href="generated/live-examples/toh-pt4/stackblitz.html">"Services" tutorial</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/toh-pt4/toh-pt4.zip">下载范例</a></span></span></span></live-example>into the <code>hero-list.component.html</code> template.</p><ul><li><p translation-result="on">给 <code>&lt;h2&gt;</code> 加文字，改成 <code>&lt;h2&gt;HEROES&lt;/h2&gt;</code>。</p><p translation-origin="off">Relabel the <code>&lt;h2&gt;</code> to <code>&lt;h2&gt;HEROES&lt;/h2&gt;</code>.</p></li><li><p translation-result="on">删除模板底部的 <code>&lt;app-hero-detail&gt;</code> 组件。</p><p translation-origin="off">Delete the <code>&lt;app-hero-detail&gt;</code> component at the bottom of the template.</p></li></ul></li></ul><ul><li><p translation-result="on">把现场演练中 <code>heroes/heroes.component.css</code> 文件的内容复制到 <code>hero-list.component.css</code> 文件中。</p><p translation-origin="off">Copy the contents of the <code>heroes/heroes.component.css</code> from the live example into the <code>hero-list.component.css</code> file.</p></li><li><p translation-result="on">把现场演练中 <code>heroes/heroes.component.ts</code> 文件的内容复制到 <code>hero-list.component.ts</code> 文件中。</p><p translation-origin="off">Copy the contents of the <code>heroes/heroes.component.ts</code> from the live example into the <code>hero-list.component.ts</code> file.</p><ul><li><p translation-result="on">把组件类名改为 <code>HeroListComponent</code>。</p><p translation-origin="off">Change the component class name to <code>HeroListComponent</code>.</p></li><li><p translation-result="on">把 <code>selector</code> 改为 <code>app-hero-list</code>。</p><p translation-origin="off">Change the <code>selector</code> to <code>app-hero-list</code>.</p></li></ul></li></ul><div class="alert is-helpful"><p translation-result="on">对于<strong>路由组件</strong>来说，这些选择器<strong>不是必须的</strong>，因为这些组件是在渲染页面时动态插入的，不过选择器对于在 HTML 元素树中标记和选中它们是很有用的。</p><p translation-origin="off">Selectors are <strong>not required</strong> for <em>routed components</em> due to the components are dynamically inserted when the page is rendered, but are useful for identifying and targeting them in your HTML element tree.</p></div><ul><li><p translation-result="on">把 <code>hero-detail</code> 目录中的 <code>hero.ts</code>、<code>hero.service.ts</code> 和 <code>mock-heroes.ts</code> 文件复制到 <code>heroes</code> 子目录下。</p><p translation-origin="off">Copy the <code>hero-detail</code> folder, the <code>hero.ts</code>, <code>hero.service.ts</code>, and <code>mock-heroes.ts</code> files into the <code>heroes</code> subfolder.</p></li><li><p translation-result="on">把 <code>message.service.ts</code> 文件复制到 <code>src/app</code> 目录下。</p><p translation-origin="off">Copy the <code>message.service.ts</code> into the <code>src/app</code> folder.</p></li><li><p translation-result="on">在 <code>hero.service.ts</code> 文件中修改导入 <code>message.service</code> 的相对路径。</p><p translation-origin="off">Update the relative path import to the <code>message.service</code> in the <code>hero.service.ts</code> file.</p></li></ul><p translation-result="on">接下来，还要修改 <code>HeroesModule</code> 的元数据。</p><p translation-origin="off">Next, you'll update the <code>HeroesModule</code> metadata.</p><ul><li><p translation-result="on">导入 <code>HeroDetailComponent</code> 和 <code>HeroListComponent</code>，并添加到 <code>HeroesModule</code> 模块的 <code>declarations</code> 数组中。</p><p translation-origin="off">Import and add the <code>HeroDetailComponent</code> and <code>HeroListComponent</code> to the <code>declarations</code> array in the <code>HeroesModule</code>.</p></li></ul><code-example path="router/src/app/heroes/heroes.module.ts" header="src/app/heroes/heroes.module.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; import { HeroesRoutingModule } from './heroes-routing.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesRoutingModule ], declarations: [ HeroListComponent, HeroDetailComponent ] }) export class HeroesModule {}</div><header class="ng-star-inserted">src/app/heroes/heroes.module.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/common'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-detail/hero-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroesRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./heroes-routing.module'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroesRoutingModule</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroDetailComponent</span><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroesModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><p translation-result="on">做完这些，你就有了四个<em>英雄管理</em>特性区的文件：</p><p translation-origin="off">When you're done, you'll have these <em>hero management</em> files:</p><div class="filetree"><div class="file"><p>src/app/heroes</p></div><div class="children"><div class="file">hero-detail</div><div class="children"><div class="file">hero-detail.component.css</div><div class="file">hero-detail.component.html</div><div class="file">hero-detail.component.ts</div></div><div class="file">hero-list</div><div class="children"><div class="file">hero-list.component.css</div><div class="file">hero-list.component.html</div><div class="file">hero-list.component.ts</div></div><div class="file"><p>hero.service.ts</p></div><div class="file">hero.ts</div><div class="file">heroes-routing.module.ts</div><div class="file"><p>heroes.module.ts</p></div><div class="file">mock-heroes.ts</div></div></div><a id="hero-routing-requirements"></a><h4 id="hero-feature-routing-requirements" translation-result="on"><em>英雄</em>特性区的路由需求<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#hero-feature-routing-requirements"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="hero-feature-routing-requirements"><em>Hero</em> feature routing requirements<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#hero-feature-routing-requirements"><i class="material-icons">link</i></a></h4><p translation-result="on">“英雄”特性有两个相互协作的组件，列表和详情。 列表视图是自给自足的，你导航到它，它会自行获取英雄列表并显示他们。</p><p translation-origin="off">The heroes feature has two interacting components, the hero list and the hero detail. The list view is self-sufficient; you navigate to it, it gets a list of heroes and displays them.</p><p translation-result="on">详情视图就不同了。它要显示一个特定的英雄，但是它本身却无法知道显示哪一个，此信息必须来自外部。</p><p translation-origin="off">The detail view is different. It displays a particular hero. It can't know which hero to show on its own. That information must come from outside.</p><p translation-result="on">当用户从列表中选择了一个英雄时，应用就导航到详情页以显示那个英雄。 通过把所选英雄的 id 编码进路由的 URL 中，就能告诉详情视图该显示哪个英雄。</p><p translation-origin="off">When the user selects a hero from the list, the app should navigate to the detail view and show that hero. You tell the detail view which hero to display by including the selected hero's id in the route URL.</p><p translation-result="on">从新位置 <code>src/app/heroes/</code> 目录中导入英雄相关的组件，定义两个“英雄管理”路由。</p><p translation-origin="off">Import the hero components from their new locations in the <code>src/app/heroes/</code> folder, define the two hero routes.</p><p translation-result="on">现在，你有了 <code>Heroes</code> 模块的路由，还得在 <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> 中把它们注册给<em>路由器</em>，和 <code>AppRoutingModule</code> 中的做法几乎完全一样。</p><p translation-origin="off">Now that you have routes for the <code>Heroes</code> module, register them with the <code><a href="api/router/Router" class="code-anchor">Router</a></code> via the <code><a href="api/router/RouterModule" class="code-anchor">RouterModule</a></code> <em>almost</em> as you did in the <code>AppRoutingModule</code>.</p><p translation-result="on">这里有少量但是关键的不同点。 在 <code>AppRoutingModule</code> 中，你使用了静态的 <code>RouterModule.</code><strong><code>forRoot</code></strong>方法来注册路由和全应用级服务提供者。 在特性模块中，你要改用<strong><code>forChild</code></strong>静态方法。</p><p translation-origin="off">There is a small but critical difference. In the <code>AppRoutingModule</code>, you used the static <strong><code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code></strong>method to register the routes and application level service providers. In a feature module you use the static <strong><code>forChild</code></strong>method.</p><div class="alert is-helpful"><p translation-result="on">只在根模块 <code>AppRoutingModule</code> 中调用 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code>（如果在 <code>AppModule</code> 中注册应用的顶层路由，那就在 <code>AppModule</code> 中调用）。 在其它模块中，你就必须调用<strong><code>RouterModule.forChild</code></strong>方法来注册附属路由。</p><p translation-origin="off">Only call <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> in the root <code>AppRoutingModule</code> (or the <code>AppModule</code> if that's where you register top level application routes). In any other module, you must call the <strong><code>RouterModule.forChild</code></strong>method to register additional routes.</p></div><p translation-result="on">修改后的 <code>HeroesRoutingModule</code> 是这样的：</p><p translation-origin="off">The updated <code>HeroesRoutingModule</code> looks like this:</p><code-example path="router/src/app/heroes/heroes-routing.module.1.ts" header="src/app/heroes/heroes-routing.module.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; const heroesRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'heroes', component: HeroListComponent }, { path: 'hero/:id', component: HeroDetailComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(heroesRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class HeroesRoutingModule { }</div><header class="ng-star-inserted">src/app/heroes/heroes-routing.module.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes-routing.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-detail/hero-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> heroesRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln">  component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">heroesRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroesRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">考虑让每个特性模块都有自己的路由配置文件。 在特性路由非常简单的早期阶段它看起来可能有点过度设计，但是，路由很容易变得更复杂，随着时间的推移，保持一致的模式会让你得到回报。</p><p translation-origin="off">Consider giving each feature module its own route configuration file. It may seem like overkill early when the feature routes are simple. But routes have a tendency to grow more complex and consistency in patterns pays off over time.</p></div><a id="remove-duplicate-hero-routes"></a><h4 id="remove-duplicate-hero-routes" translation-result="on">移除重复的“英雄管理”路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#remove-duplicate-hero-routes"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="remove-duplicate-hero-routes">Remove duplicate hero routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#remove-duplicate-hero-routes"><i class="material-icons">link</i></a></h4><p translation-result="on">英雄类的路由目前定义在两个地方：<code>HeroesRoutingModule</code> 中（并最终给 <code>HeroesModule</code>）和 <code>AppRoutingModule</code> 中。</p><p translation-origin="off">The hero routes are currently defined in <em>two</em> places: in the <code>HeroesRoutingModule</code>, by way of the <code>HeroesModule</code>, and in the <code>AppRoutingModule</code>.</p><p translation-result="on">由特性模块提供的路由会被路由器再组合上它们所导入的模块的路由。 这让你可以继续定义特性路由模块中的路由，而不用修改主路由配置。</p><p translation-origin="off">Routes provided by feature modules are combined together into their imported module's routes by the router. This allows you to continue defining the feature module routes without modifying the main route configuration.</p><p translation-result="on">移除 <code>HeroListComponent</code> 的导入和来自 <code>app-routing.module.ts</code> 中的 <code>/heroes</code> 路由。</p><p translation-origin="off">Remove the <code>HeroListComponent</code> import and the <code>/heroes</code> route from the <code>app-routing.module.ts</code>.</p><p translation-result="on"><strong>保留默认路由和通配符路由！</strong> 它们是应用程序顶层该自己处理的关注点。</p><p translation-origin="off"><strong>Leave the default and the wildcard routes!</strong> These are concerns at the top level of the application itself.</p><code-example path="router/src/app/app-routing.module.2.ts" header="src/app/app-routing.module.ts (v2)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; // import { HeroListComponent } from './hero-list/hero-list.component'; // &lt;-- delete this line import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, // { path: 'heroes', component: HeroListComponent }, // &lt;-- delete this line { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule {}</div><header class="ng-star-inserted">src/app/app-routing.module.ts (v2)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (v2)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">              </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// import { HeroListComponent }  from './hero-list/hero-list.component';  // &lt;-- delete this line</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="com">// { path: 'heroes',     component: HeroListComponent }, // &lt;-- delete this line</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">   </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><a id="merge-hero-routes"></a><h4 id="remove-heroes-declarations" translation-result="on">移除英雄列表的声明<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#remove-heroes-declarations"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="remove-heroes-declarations">Remove heroes declarations<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#remove-heroes-declarations"><i class="material-icons">link</i></a></h4><p translation-result="on">从 <code>AppModule</code> 的 <code>declarations</code> 中移除 <code>HeroListComponent</code>，因为它现在已经改由 <code>HeroesModule</code> 提供了。 你可以让“英雄”特性独立演化，添加更多的组件或各种各样的路由。 这就是为每个特性区创建独立模块后获得的核心优势。</p><p translation-origin="off">Remove the <code>HeroListComponent</code> from the <code>AppModule</code>'s <code>declarations</code> because it's now provided by the <code>HeroesModule</code>. You can evolve the hero feature with more components and different routes. That's a key benefit of creating a separate module for each feature area.</p><p translation-result="on">经过这些步骤，<code>AppModule</code> 变成了这样：</p><p translation-origin="off">After these steps, the <code>AppModule</code> should look like this:</p><code-example path="router/src/app/app.module.3.ts" header="src/app/app.module.ts" region="remove-heroes" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, AppRoutingModule ], declarations: [ AppComponent, CrisisListComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app-routing.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroesModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./heroes/heroes.module'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroesModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AppRoutingModule</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><a id="routing-module-order"></a><h3 id="module-import-order-matters" translation-result="on">导入模块的顺序很重要<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#module-import-order-matters"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="module-import-order-matters">Module import order matters<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#module-import-order-matters"><i class="material-icons">link</i></a></h3><p translation-result="on">看看该模块的 <code>imports</code> 数组。注意，<code>AppRoutingModule</code> 是<em>最后一个</em>。最重要的是，它位于 <code>HeroesModule</code> 之后。</p><p translation-origin="off">Look at the module <code>imports</code> array. Notice that the <code>AppRoutingModule</code> is <em>last</em>. Most importantly, it comes <em>after</em> the <code>HeroesModule</code>.</p><code-example path="router/src/app/app.module.3.ts" region="module-imports" header="src/app/app.module.ts (module-imports)" ng-version="9.0.0-rc.11"><div style="display:none">imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, AppRoutingModule ],</div><header class="ng-star-inserted">src/app/app.module.ts (module-imports)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (module-imports)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
  </span><span class="typ">HeroesModule</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">AppRoutingModule</span><span class="pln">
</span><span class="pun">],</span></code>
    </pre></aio-code></code-example><p translation-result="on">路由配置的顺序很重要。 路由器会接受第一个匹配上导航所要求的路径的那个路由。</p><p translation-origin="off">The order of route configuration matters. The router accepts the first route that matches a navigation request path.</p><p translation-result="on">当所有路由都在同一个 <code>AppRoutingModule</code> 时，你要把默认路由和<a href="guide/router#wildcard">通配符路由</a>放在最后（这里是在 <code>/heroes</code> 路由后面）， 这样路由器才有机会匹配到 <code>/heroes</code> 路由，否则它就会先遇到并匹配上该通配符路由，并导航到“页面未找到”路由。</p><p translation-origin="off">When all routes were in one <code>AppRoutingModule</code>, you put the default and <a href="guide/router#wildcard">wildcard</a> routes last, after the <code>/heroes</code> route, so that the router had a chance to match a URL to the <code>/heroes</code> route <em>before</em> hitting the wildcard route and navigating to "Page not found".</p><p translation-result="on">这些路由不再位于单一文件中。他们分布在两个不同的模块中：<code>AppRoutingModule</code> 和 <code>HeroesRoutingModule</code>。</p><p translation-origin="off">The routes are no longer in one file. They are distributed across two modules, <code>AppRoutingModule</code> and <code>HeroesRoutingModule</code>.</p><p translation-result="on">每个路由模块都会根据<em>导入的顺序</em>把自己的路由配置追加进去。 如果你先列出了 <code>AppRoutingModule</code>，那么通配符路由就会被注册在“英雄管理”路由<em>之前</em>。 通配符路由（它匹配<em>任意</em>URL）将会拦截住每一个到“英雄管理”路由的导航，因此事实上屏蔽了所有“英雄管理”路由。</p><p translation-origin="off">Each routing module augments the route configuration <em>in the order of import</em>. If you list <code>AppRoutingModule</code> first, the wildcard route will be registered <em>before</em> the hero routes. The wildcard route—which matches <em>every</em> URL—will intercept the attempt to navigate to a hero route.</p><div class="alert is-helpful"><p translation-result="on">反转路由模块的导入顺序，你就会看到当点击英雄相关的链接时被导向了“页面未找到”路由。 要学习如何在运行时查看路由器配置，参见<a href="guide/router#inspect-config" title="Inspect the router config">稍后的内容</a>。</p><p translation-origin="off">Reverse the routing modules and see for yourself that a click of the heroes link results in "Page not found". Learn about inspecting the runtime router configuration <a href="guide/router#inspect-config" title="Inspect the router config">below</a>.</p></div><h3 id="route-parameters" translation-result="on">路由参数<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="route-parameters">Route Parameters<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters"><i class="material-icons">link</i></a></h3><a id="route-def-with-parameter"></a><h4 id="route-definition-with-a-parameter" translation-result="on">带参数的路由定义<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-definition-with-a-parameter"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="route-definition-with-a-parameter">Route definition with a parameter<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-definition-with-a-parameter"><i class="material-icons">link</i></a></h4><p translation-result="on">回到 <code>HeroesRoutingModule</code> 并再次检查这些路由定义。 <code>HeroDetailComponent</code> 的路由有点特殊。</p><p translation-origin="off">Return to the <code>HeroesRoutingModule</code> and look at the route definitions again. The route to <code>HeroDetailComponent</code> has a twist.</p><code-example path="router/src/app/heroes/heroes-routing.module.1.ts" header="src/app/heroes/heroes-routing.module.ts (excerpt)" region="hero-detail-route" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'hero/:id', component: HeroDetailComponent }</div><header class="ng-star-inserted">src/app/heroes/heroes-routing.module.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes-routing.module.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意路径中的 <code>:id</code> 令牌。它为<em>路由参数</em>在路径中创建一个“空位”。在这里，路由器把英雄的 <code>id</code> 插入到那个“空位”中。</p><p translation-origin="off">Notice the <code>:id</code> token in the path. That creates a slot in the path for a <strong>Route Parameter</strong>. In this case, the router will insert the <code>id</code> of a hero into that slot.</p><p translation-result="on">如果要告诉路由器导航到详情组件，并让它显示“Magneta”，你会期望这个英雄的 <code>id</code> 像这样显示在浏览器的 URL 中：</p><p translation-origin="off">If you tell the router to navigate to the detail component and display "Magneta", you expect a hero id to appear in the browser URL like this:</p><code-example format="nocode" ng-version="9.0.0-rc.11"><div style="display:none">localhost:4200/hero/15</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">4200</span><span class="pun">/</span><span class="pln">hero</span><span class="pun">/</span><span class="lit">15</span></code>
    </pre></aio-code></code-example><p translation-result="on">如果用户把此 URL 输入到浏览器的地址栏中，路由器就会识别出这种模式，同样进入“Magneta”的详情视图。</p><p translation-origin="off">If a user enters that URL into the browser address bar, the router should recognize the pattern and go to the same "Magneta" detail view.</p><div class="callout is-helpful"><header translation-result="on">路由参数：必须的还是可选的？</header><header translation-origin="off">Route parameter: Required or optional?</header><p translation-result="on">在这个场景下，把路由参数的令牌 <code>:id</code> 嵌入到路由定义的 <code>path</code> 中是一个好主意，因为对于 <code>HeroDetailComponent</code> 来说 <code>id</code> 是<em>必须的</em>， 而且路径中的值 <code>15</code> 已经足够把到“Magneta”的路由和到其它英雄的路由明确区分开。</p><p translation-origin="off">Embedding the route parameter token, <code>:id</code>, in the route definition path is a good choice for this scenario because the <code>id</code> is <em>required</em> by the <code>HeroDetailComponent</code> and because the value <code>15</code> in the path clearly distinguishes the route to "Magneta" from a route for some other hero.</p></div><a id="route-parameters"></a><h4 id="setting-the-route-parameters-in-the-list-view" translation-result="on">在列表视图中设置路由参数<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#setting-the-route-parameters-in-the-list-view"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="setting-the-route-parameters-in-the-list-view">Setting the route parameters in the list view<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#setting-the-route-parameters-in-the-list-view"><i class="material-icons">link</i></a></h4><p translation-result="on">然后导航到 <code>HeroDetailComponent</code> 组件。在那里，你期望看到所选英雄的详情，这需要两部分信息：导航目标和该英雄的 <code>id</code>。</p><p translation-origin="off">After navigating to the <code>HeroDetailComponent</code>, you expect to see the details of the selected hero. You need <em>two</em> pieces of information: the routing path to the component and the hero's <code>id</code>.</p><p translation-result="on">因此，这个<em>链接参数数组</em>中有两个条目：目标路由的<strong><code>path</code>（路径）</strong>，和一个用来指定所选英雄 <code>id</code> 的<strong>路由参数</strong>。</p><p translation-origin="off">Accordingly, the <em>link parameters array</em> has <em>two</em> items: the routing <em>path</em> and a <em>route parameter</em> that specifies the <code>id</code> of the selected hero.</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.1.html" header="src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)" region="link-parameters-array" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/hero', hero.id]"&gt;</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/hero', hero.id]"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">路由器从该数组中组合出了目标 URL： <code>localhost:3000/hero/15</code>。</p><p translation-origin="off">The router composes the destination URL from the array like this: <code>localhost:4200/hero/15</code>.</p><div class="alert is-helpful"><p translation-result="on">目标组件 <code>HeroDetailComponent</code> 该怎么知道这个 <code>id</code> 参数呢？ 当然不会是自己去分析 URL 了！那是路由器的工作。</p><p translation-origin="off">How does the target <code>HeroDetailComponent</code> learn about that <code>id</code>? Don't analyze the URL. Let the router do it.</p><p translation-result="on">路由器从 URL 中解析出路由参数（<code>id:15</code>），并通过 <strong>ActivatedRoute</strong> 服务来把它提供给 <code>HeroDetailComponent</code> 组件。</p><p translation-origin="off">The router extracts the route parameter (<code>id:15</code>) from the URL and supplies it to the <code>HeroDetailComponent</code> via the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> service.</p></div><a id="activated-route"></a><h3 id="activated-route-in-action" translation-result="on"><em>Activated Route</em> 实战<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#activated-route-in-action"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="activated-route-in-action"><em>Activated Route</em> in action<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#activated-route-in-action"><i class="material-icons">link</i></a></h3><p translation-result="on">从路由器（<code>router</code>）包中导入 <code><a href="api/router/Router" class="code-anchor">Router</a></code>、<code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 和 <code><a href="api/router/Params" class="code-anchor">Params</a></code> 类。</p><p translation-origin="off">Import the <code><a href="api/router/Router" class="code-anchor">Router</a></code>, <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>, and <code><a href="api/router/ParamMap" class="code-anchor">ParamMap</a></code> tokens from the router package.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.1.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (activated route)" region="imports" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, <a href="api/router/ParamMap" class="code-anchor">ParamMap</a> } from '@angular/router';</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (activated route)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (activated route)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/ParamMap" class="code-anchor"><span class="typ">ParamMap</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span></code>
    </pre></aio-code></code-example><p translation-result="on">这里导入 <code>switchMap</code> 操作符是因为你稍后将会处理路由参数的可观察对象 <code>Observable</code>。</p><p translation-origin="off">Import the <code>switchMap</code> operator because you need it later to process the <code>Observable</code> route parameters.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.3.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (switchMap operator import)" region="rxjs-operator-import" ng-version="9.0.0-rc.11"><div style="display:none">import { switchMap } from 'rxjs/operators';</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (switchMap operator import)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (switchMap operator import)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> switchMap </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span></code>
    </pre></aio-code></code-example><a id="hero-detail-ctor"></a><p translation-result="on">通常，你会直接写一个构造函数，让 Angular 把组件所需的服务注入进来，自动定义同名的私有变量，并把它们存进去。</p><p translation-origin="off">As usual, you write a constructor that asks Angular to inject services that the component requires and reference them as private variables.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.3.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (constructor)" region="ctor" ng-version="9.0.0-rc.11"><div style="display:none">constructor( private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, private router: <a href="api/router/Router" class="code-anchor">Router</a>, private service: HeroService ) {}</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (constructor)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (constructor)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">
  </span><span class="kwd">private</span><span class="pln"> route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pun">,</span><span class="pln">
  </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln">
  </span><span class="kwd">private</span><span class="pln"> service</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroService</span><span class="pln">
</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><p translation-result="on">然后，在 <code>ngOnInit</code> 方法中，你用 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 服务来接收路由的参数，从参数中取得该英雄的 <code>id</code>，并接收此英雄用于显示。</p><p translation-origin="off">Later, in the <code>ngOnInit</code> method, you use the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> service to retrieve the parameters for the route, pull the hero <code>id</code> from the parameters and retrieve the hero to display.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.3.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit)" region="ngOnInit" ng-version="9.0.0-rc.11"><div style="display:none">ngOnInit() { this.hero$ = this.route.paramMap.pipe( switchMap((params: <a href="api/router/ParamMap" class="code-anchor">ParamMap</a>) =&gt; this.service.getHero(params.get('id'))) ); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">hero$ </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route</span><span class="pun">.</span><span class="pln">paramMap</span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">
    switchMap</span><span class="pun">((</span><span class="kwd">params</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ParamMap" class="code-anchor"><span class="typ">ParamMap</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">service</span><span class="pun">.</span><span class="pln">getHero</span><span class="pun">(</span><span class="kwd">params</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">)))</span><span class="pln">
  </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>paramMap</code> 的处理过程有点稍复杂。当这个 map 的值变化时，你可以从变化之后的参数中 <code>get()</code> 到其 <code>id</code> 参数。</p><p translation-origin="off">The <code>paramMap</code> processing is a bit tricky. When the map changes, you <code>get()</code> the <code>id</code> parameter from the changed parameters.</p><p translation-result="on">然后，让 <code>HeroService</code> 去获取一个具有此 <code>id</code> 的英雄，并返回这个 <code>HeroService</code> 请求的结果。</p><p translation-origin="off">Then you tell the <code>HeroService</code> to fetch the hero with that <code>id</code> and return the result of the <code>HeroService</code> request.</p><p translation-result="on">你可能想使用 RxJS 的 <code>map</code> 操作符。 但 <code>HeroService</code> 返回的是一个 <code>Observable&lt;Hero&gt;</code>。 所以你要改用 <code>switchMap</code> 操作符来打平这个 <code>Observable</code>。</p><p translation-origin="off">You might think to use the RxJS <code>map</code> operator. But the <code>HeroService</code> returns an <code>Observable&lt;Hero&gt;</code>. So you flatten the <code>Observable</code> with the <code>switchMap</code> operator instead.</p><p translation-result="on"><code>switchMap</code> 操作符还会取消以前未完成的在途请求。如果用户使用新的 <code>id</code> 再次导航到该路由，而 <code>HeroService</code> 仍在接受老 <code>id</code> 对应的英雄，那么 <code>switchMap</code> 就会抛弃老的请求，并返回这个新 <code>id</code> 的英雄信息。</p><p translation-origin="off">The <code>switchMap</code> operator also cancels previous in-flight requests. If the user re-navigates to this route with a new <code>id</code> while the <code>HeroService</code> is still retrieving the old <code>id</code>, <code>switchMap</code> discards that old request and returns the hero for the new <code>id</code>.</p><p translation-result="on">这个可观察对象的 <code>Subscription</code>（订阅）将会由 <code><a href="api/common/AsyncPipe" class="code-anchor">AsyncPipe</a></code> 处理，并且组件的 <code>hero</code> 属性将会设置为刚刚接收到的这个英雄。</p><p translation-origin="off">The observable <code>Subscription</code> will be handled by the <code><a href="api/common/AsyncPipe" class="code-anchor">AsyncPipe</a></code> and the component's <code>hero</code> property will be (re)set with the retrieved hero.</p><h4 id="parammap-api"><em>ParamMap</em> API<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#parammap-api"><i class="material-icons">link</i></a></h4><p translation-result="on"><code><a href="api/router/ParamMap" class="code-anchor">ParamMap</a></code> API 是参照<a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams">URLSearchParams 接口</a>来设计的。它提供了一些方法来处理对路由参数（<code>paramMap</code>）和查询参数(<code>queryParamMap</code>)中的参数访问。</p><p translation-origin="off">The <code><a href="api/router/ParamMap" class="code-anchor">ParamMap</a></code> API is inspired by the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams">URLSearchParams interface</a>. It provides methods to handle parameter access for both route parameters (<code>paramMap</code>) and query parameters (<code>queryParamMap</code>).</p><table><tbody><tr><th><p translation-result="on">成员</p><p translation-origin="off">Member</p></th><th><p translation-result="on">说明</p><p translation-origin="off">Description</p></th></tr><tr><td><p> <code>has(name)</code></p></td><td><p translation-result="on">如果参数名位于参数列表中，就返回 <code>true</code> 。</p><p translation-origin="off">Returns <code>true</code> if the parameter name is in the map of parameters.</p></td></tr><tr><td><p> <code>get(name)</code></p></td><td><p translation-result="on">如果这个 map 中有参数名对应的参数值（字符串），就返回它，否则返回 <code>null</code>。如果参数值实际上是一个数组，就返回它的<em>第一个</em>元素。</p><p translation-origin="off">Returns the parameter name value (a <code>string</code>) if present, or <code>null</code> if the parameter name is not in the map. Returns the <em>first</em> element if the parameter value is actually an array of values.</p></td></tr><tr><td><p> <code>getAll(name)</code></p></td><td><p translation-result="on">如果这个 map 中有参数名对应的值，就返回一个字符串数组，否则返回空数组。当一个参数名可能对应多个值的时候，请使用 <code>getAll</code>。</p><p translation-origin="off">Returns a <code>string array</code> of the parameter name value if found, or an empty <code>array</code> if the parameter name value is not in the map. Use <code>getAll</code> when a single parameter could have multiple values.</p></td></tr><tr><td><p> <code><a href="api/router/ParamMap#keys" class="code-anchor">keys</a></code></p></td><td><p translation-result="on">返回这个 map 中的所有参数名组成的字符串数组。</p><p translation-origin="off">Returns a <code>string array</code> of all parameter names in the map.</p></td></tr></tbody></table><a id="reuse"></a><h4 id="observable-parammap-and-component-reuse" translation-result="on"><i>参数</i>的可观察对象（Observable）与组件复用<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#observable-parammap-and-component-reuse"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="observable-parammap-and-component-reuse">Observable <i>paramMap</i> and component reuse<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#observable-parammap-and-component-reuse"><i class="material-icons">link</i></a></h4><p translation-result="on">在这个例子中，你接收了路由参数的 <code>Observable</code> 对象。 这种写法暗示着这些路由参数在该组件的生存期内可能会变化。</p><p translation-origin="off">In this example, you retrieve the route parameter map from an <code>Observable</code>. That implies that the route parameter map can change during the lifetime of this component.</p><p translation-result="on">确实如此！默认情况下，如果它没有访问过其它组件就导航到了同一个组件实例，那么路由器倾向于复用组件实例。如果复用，这些参数可以变化。</p><p translation-origin="off">They might. By default, the router re-uses a component instance when it re-navigates to the same component type without visiting a different component first. The route parameters could change each time.</p><p translation-result="on">假设父组件的导航栏有“前进”和“后退”按钮，用来轮流显示英雄列表中中英雄的详情。 每次点击都会强制导航到带前一个或后一个 <code>id</code> 的 <code>HeroDetailComponent</code> 组件。</p><p translation-origin="off">Suppose a parent component navigation bar had "forward" and "back" buttons that scrolled through the list of heroes. Each click navigated imperatively to the <code>HeroDetailComponent</code> with the next or previous <code>id</code>.</p><p translation-result="on">你不希望路由器仅仅从 DOM 中移除当前的 <code>HeroDetailComponent</code> 实例，并且用下一个 <code>id</code> 重新创建它。 那可能导致界面抖动。 更好的方式是复用同一个组件实例，并更新这些参数。</p><p translation-origin="off">You don't want the router to remove the current <code>HeroDetailComponent</code> instance from the DOM only to re-create it for the next <code>id</code>. That could be visibly jarring. Better to simply re-use the same component instance and update the parameter.</p><p translation-result="on">不幸的是，<code>ngOnInit</code> 对每个实例只调用一次。 你需要一种方式来检测<em>在同一个实例中</em>路由参数什么时候发生了变化。 而 <code>params</code> 属性这个可观察对象（Observable）干净漂亮地处理了这种情况。</p><p translation-origin="off">Unfortunately, <code>ngOnInit</code> is only called once per component instantiation. You need a way to detect when the route parameters change from <em>within the same instance</em>. The observable <code>paramMap</code> property handles that beautifully.</p><div class="alert is-helpful"><p translation-result="on">当在组件中订阅一个可观察对象时，你通常总是要在组件销毁时取消这个订阅。</p><p translation-origin="off">When subscribing to an observable in a component, you almost always arrange to unsubscribe when the component is destroyed.</p><p translation-result="on">但是也有少数例外情况不需要取消订阅。 <code>ActivateRoute</code> 中的各种可观察对象就是属于这种情况。</p><p translation-origin="off">There are a few exceptional observables where this is not necessary. The <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> observables are among the exceptions.</p><p translation-result="on"><code>ActivateRoute</code> 及其可观察对象都是由 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 本身负责管理的。 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 会在不再需要时销毁这个路由组件，而注入进去的 <code>ActivateRoute</code> 也随之销毁了。</p><p translation-origin="off">The <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> and its observables are insulated from the <code><a href="api/router/Router" class="code-anchor">Router</a></code> itself. The <code><a href="api/router/Router" class="code-anchor">Router</a></code> destroys a routed component when it is no longer needed and the injected <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> dies with it.</p><p translation-result="on">不过，你仍然可以随意取消订阅，这不会造成任何损害，而且也不是一项坏的实践。</p><p translation-origin="off">Feel free to unsubscribe anyway. It is harmless and never a bad practice.</p></div><a id="snapshot"></a><h4 id="snapshot-the-no-observable-alternative" translation-result="on"><em>Snapshot</em>（快照）：当不需要 Observable 时的替代品<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#snapshot-the-no-observable-alternative"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="snapshot-the-no-observable-alternative"><em>Snapshot</em>: the <em>no-observable</em> alternative<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#snapshot-the-no-observable-alternative"><i class="material-icons">link</i></a></h4><p translation-result="on">本应用不需要复用 <code>HeroDetailComponent</code>。 用户总是会先返回英雄列表，再选择另一位英雄。 所以，不存在从一个英雄详情导航到另一个而不用经过英雄列表的情况。 这意味着路由器每次都会创建一个全新的 <code>HeroDetailComponent</code> 实例。</p><p translation-origin="off"><em>This</em> application won't re-use the <code>HeroDetailComponent</code>. The user always returns to the hero list to select another hero to view. There's no way to navigate from one hero detail to another hero detail without visiting the list component in between. Therefore, the router creates a new <code>HeroDetailComponent</code> instance every time.</p><p translation-result="on">假如你很确定这个 <code>HeroDetailComponent</code> 组件的实例<em>永远、永远</em>不会被复用，那就可以使用<em>快照</em>来简化这段代码。</p><p translation-origin="off">When you know for certain that a <code>HeroDetailComponent</code> instance will <em>never, never, ever</em> be re-used, you can simplify the code with the <em>snapshot</em>.</p><p translation-result="on"><code>route.snapshot</code> 提供了路由参数的初始值。 你可以通过它来直接访问参数，而不用订阅或者添加 Observable 的操作符。 这样在读写时就会更简单：</p><p translation-origin="off">The <code>route.snapshot</code> provides the initial value of the route parameter map. You can access the parameters directly without subscribing or adding observable operators. It's much simpler to write and read:</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.2.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit snapshot)" region="snapshot" ng-version="9.0.0-rc.11"><div style="display:none">ngOnInit() { let id = this.route.snapshot.paramMap.get('id'); this.hero$ = this.service.getHero(id); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit snapshot)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit snapshot)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">let</span><span class="pln"> id </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route</span><span class="pun">.</span><span class="pln">snapshot</span><span class="pun">.</span><span class="pln">paramMap</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">

  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">hero$ </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">service</span><span class="pun">.</span><span class="pln">getHero</span><span class="pun">(</span><span class="pln">id</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on"><strong>记住：</strong>，用这种技巧，你只得到了这些参数的<em>初始</em>值。 如果有可能连续多次导航到此组件，那么就该用 <code>paramMap</code> 可观察对象的方式。 这个例子中仍然使用了 <code>paramMap</code> 的可观察对象策略。</p><p translation-origin="off"><strong>Remember:</strong> you only get the <em>initial</em> value of the parameter map with this technique. Stick with the observable <code>paramMap</code> approach if there's even a chance that the router could re-use the component. This sample stays with the observable <code>paramMap</code> strategy just in case.</p></div><a id="nav-to-list"></a><h3 id="navigating-back-to-the-list-component" translation-result="on">导航回列表组件<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#navigating-back-to-the-list-component"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="navigating-back-to-the-list-component">Navigating back to the list component<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#navigating-back-to-the-list-component"><i class="material-icons">link</i></a></h3><p translation-result="on"><code>HeroDetailComponent</code> 组件有一个“Back”按钮，关联到它的 <code>gotoHeroes</code> 方法，该方法会导航回 <code>HeroListComponent</code> 组件。</p><p translation-origin="off">The <code>HeroDetailComponent</code> has a "Back" button wired to its <code>gotoHeroes</code> method that navigates imperatively back to the <code>HeroListComponent</code>.</p><p translation-result="on">路由的 <code>navigate</code> 方法同样接受一个单条目的<em>链接参数数组</em>，你也可以把它绑定到 <code>[<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]</code> 指令上。 它保存着<strong>到 <code>HeroListComponent</code> 组件的路径</strong>：</p><p translation-origin="off">The router <code>navigate</code> method takes the same one-item <em>link parameters array</em> that you can bind to a <code>[<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]</code> directive. It holds the <em>path to the <code>HeroListComponent</code></em>:</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.1.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (excerpt)" region="gotoHeroes" ng-version="9.0.0-rc.11"><div style="display:none">gotoHeroes() { this.router.navigate(['/heroes']); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">gotoHeroes</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/heroes'</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><a id="optional-route-parameters"></a><h4 id="route-parameters-required-or-optional" translation-result="on">路由参数：必须还是可选？<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters-required-or-optional"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="route-parameters-required-or-optional">Route Parameters: Required or optional?<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters-required-or-optional"><i class="material-icons">link</i></a></h4><p translation-result="on">如果想导航到 <code>HeroDetailComponent</code> 以对 id 为 15 的英雄进行查看并编辑，就要在路由的 URL 中使用<a href="guide/router#route-parameters"><em>路由参数</em></a>来指定<em>必要</em>参数值。</p><p translation-origin="off">Use <a href="guide/router#route-parameters"><em>route parameters</em></a> to specify a <em>required</em> parameter value <em>within</em> the route URL as you do when navigating to the <code>HeroDetailComponent</code> in order to view the hero with <em>id</em> 15:</p><code-example format="nocode" ng-version="9.0.0-rc.11"><div style="display:none">localhost:4200/hero/15</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">4200</span><span class="pun">/</span><span class="pln">hero</span><span class="pun">/</span><span class="lit">15</span></code>
    </pre></aio-code></code-example><p translation-result="on">你也能在路由请求中添加<em>可选</em>信息。 比如，当从 hero-detail.component.ts 返回到列表时，如果能自动选中刚刚查看过的英雄就好了。</p><p translation-origin="off">You can also add <em>optional</em> information to a route request. For example, when returning to the hero-detail.component.ts list from the hero detail view, it would be nice if the viewed hero was preselected in the list.</p><div class="lightbox"><img src="generated/images/guide/router/selected-hero.png" alt="Selected hero" width="336" height="110"></div><p translation-result="on">当从 <code>HeroDetailComponent</code> 返回时，你很快就会通过把正在查看的英雄的 <code>id</code> 作为可选参数包含在 URL 中来实现这个特性。</p><p translation-origin="off">You'll implement this feature in a moment by including the viewed hero's <code>id</code> in the URL as an optional parameter when returning from the <code>HeroDetailComponent</code>.</p><p translation-result="on">可选信息有很多种形式。搜索条件通常就不是严格结构化的，比如 <code>name='wind*'</code>；有多个值也很常见，如 <code>after='12/31/2015'&amp;before='1/1/2017'</code>； 而且顺序无关，如 <code>before='1/1/2017'&amp;after='12/31/2015'</code>，还可能有很多种变体格式，如 <code>during='currentYear'</code>。</p><p translation-origin="off">Optional information takes other forms. Search criteria are often loosely structured, e.g., <code>name='wind*'</code>. Multiple values are common—<code>after='12/31/2015' &amp; before='1/1/2017'</code>—in no particular order—<code>before='1/1/2017' &amp; after='12/31/2015'</code>— in a variety of formats—<code>during='currentYear'</code>.</p><p translation-result="on">这么多种参数要放在 URL 的<em>路径</em>中可不容易。即使你能制定出一个合适的 URL 方案，实现起来也太复杂了，得通过模式匹配才能把 URL 翻译成命名路由。</p><p translation-origin="off">These kinds of parameters don't fit easily in a URL <em>path</em>. Even if you could define a suitable URL token scheme, doing so greatly complicates the pattern matching required to translate an incoming URL to a named route.</p><p translation-result="on">可选参数是在导航期间传送任意复杂信息的理想载体。 可选参数不涉及到模式匹配并在表达上提供了巨大的灵活性。</p><p translation-origin="off">Optional parameters are the ideal vehicle for conveying arbitrarily complex information during navigation. Optional parameters aren't involved in pattern matching and afford flexibility of expression.</p><p translation-result="on">和必要参数一样，路由器也支持通过可选参数导航。 在你定义完必要参数之后，再通过一个<em>独立的对象</em>来定义<em>可选参数</em>。</p><p translation-origin="off">The router supports navigation with optional parameters as well as required route parameters. Define <em>optional</em> parameters in a separate object <em>after</em> you define the required route parameters.</p><p translation-result="on">通常，对于强制性的值（比如用于区分两个路由路径的）使用<em>必备参数</em>；当这个值是可选的、复杂的或多值的时，使用可选参数。</p><p translation-origin="off">In general, prefer a <em>required route parameter</em> when the value is mandatory (for example, if necessary to distinguish one route path from another); prefer an <em>optional parameter</em> when the value is optional, complex, and/or multivariate.</p><a id="optionally-selecting"></a><h4 id="heroes-list-optionally-selecting-a-hero" translation-result="on">英雄列表：选定一个英雄（也可不选）<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#heroes-list-optionally-selecting-a-hero"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="heroes-list-optionally-selecting-a-hero">Heroes list: optionally selecting a hero<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#heroes-list-optionally-selecting-a-hero"><i class="material-icons">link</i></a></h4><p translation-result="on">当导航到 <code>HeroDetailComponent</code> 时，你可以在<em>路由参数</em>中指定一个所要编辑的英雄 <code>id</code>，只要把它作为<a href="guide/router#link-parameters-array">链接参数数组</a>中的第二个条目就可以了。</p><p translation-origin="off">When navigating to the <code>HeroDetailComponent</code> you specified the <em>required</em> <code>id</code> of the hero-to-edit in the <em>route parameter</em> and made it the second item of the <a href="guide/router#link-parameters-array"><em>link parameters array</em></a>.</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.1.html" header="src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)" region="link-parameters-array" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/hero', hero.id]"&gt;</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/hero', hero.id]"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">路由器在导航 URL 中内嵌了 <code>id</code> 的值，这是因为你把它用一个 <code>:id</code> 占位符当做路由参数定义在了路由的 <code>path</code> 中：</p><p translation-origin="off">The router embedded the <code>id</code> value in the navigation URL because you had defined it as a route parameter with an <code>:id</code> placeholder token in the route <code>path</code>:</p><code-example path="router/src/app/heroes/heroes-routing.module.1.ts" header="src/app/heroes/heroes-routing.module.ts (hero-detail-route)" region="hero-detail-route" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'hero/:id', component: HeroDetailComponent }</div><header class="ng-star-inserted">src/app/heroes/heroes-routing.module.ts (hero-detail-route)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes-routing.module.ts (hero-detail-route)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">当用户点击后退按钮时，<code>HeroDetailComponent</code> 构造了另一个<em>链接参数数组</em>，可以用它导航回 <code>HeroListComponent</code>。</p><p translation-origin="off">When the user clicks the back button, the <code>HeroDetailComponent</code> constructs another <em>link parameters array</em> which it uses to navigate back to the <code>HeroListComponent</code>.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.1.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (gotoHeroes)" region="gotoHeroes" ng-version="9.0.0-rc.11"><div style="display:none">gotoHeroes() { this.router.navigate(['/heroes']); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (gotoHeroes)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (gotoHeroes)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">gotoHeroes</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/heroes'</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">该数组缺少一个路由参数，这是因为你那时没有理由往 <code>HeroListComponent</code> 发送信息。</p><p translation-origin="off">This array lacks a route parameter because you had no reason to send information to the <code>HeroListComponent</code>.</p><p translation-result="on">但现在有了。你要在导航请求中同时发送当前英雄的 id，以便 <code>HeroListComponent</code> 可以在列表中高亮这个英雄。 这是一个<em>有更好，没有也无所谓</em>的特性，就算没有它，列表照样能显示得很完美。</p><p translation-origin="off">Now you have a reason. You'd like to send the id of the current hero with the navigation request so that the <code>HeroListComponent</code> can highlight that hero in its list. This is a <em>nice-to-have</em> feature; the list will display perfectly well without it.</p><p translation-result="on">传送一个包含<em>可选</em><code>id</code> 参数的对象。 为了演示，这里还在对象中定义了一个没用的额外参数（<code>foo</code>），<code>HeroListComponent</code> 应该忽略它。 下面是修改过的导航语句：</p><p translation-origin="off">Send the <code>id</code> with an object that contains an <em>optional</em> <code>id</code> parameter. For demonstration purposes, there's an extra junk parameter (<code>foo</code>) in the object that the <code>HeroListComponent</code> should ignore. Here's the revised navigation statement:</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.3.ts" header="src/app/heroes/hero-detail/hero-detail.component.ts (go to heroes)" region="gotoHeroes" ng-version="9.0.0-rc.11"><div style="display:none">gotoHeroes(hero: Hero) { let heroId = hero ? hero.id : null; // Pass along the hero id if available // so that the HeroList component can select that hero. // Include a junk 'foo' property for fun. this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (go to heroes)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (go to heroes)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">gotoHeroes</span><span class="pun">(</span><span class="pln">hero</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">let</span><span class="pln"> heroId </span><span class="pun">=</span><span class="pln"> hero </span><span class="pun">?</span><span class="pln"> hero</span><span class="pun">.</span><span class="pln">id </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
  </span><span class="com">// Pass along the hero id if available</span><span class="pln">
  </span><span class="com">// so that the HeroList component can select that hero.</span><span class="pln">
  </span><span class="com">// Include a junk 'foo' property for fun.</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> heroId</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">:</span><span class="pln"> </span><span class="str">'foo'</span><span class="pln"> </span><span class="pun">}]);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">该应用仍然能工作。点击“back”按钮返回英雄列表视图。</p><p translation-origin="off">The application still works. Clicking "back" returns to the hero list view.</p><p translation-result="on">注意浏览器的地址栏。</p><p translation-origin="off">Look at the browser address bar.</p><p translation-result="on">它应该是这样的，不过也取决于你在哪里运行它：</p><p translation-origin="off">It should look something like this, depending on where you run it:</p><code-example language="bash" ng-version="9.0.0-rc.11"><div style="display:none">localhost:4200/heroes;id=15;foo=foo</div><aio-code><pre class="lang-bash prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">4200</span><span class="pun">/</span><span class="pln">heroes</span><span class="pun">;</span><span class="pln">id</span><span class="pun">=</span><span class="lit">15</span><span class="pun">;</span><span class="pln">foo</span><span class="pun">=</span><span class="pln">foo</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>id</code> 的值像这样出现在 URL 中（<code>;id=15;foo=foo</code>），但不在 URL 的路径部分。 “Heroes”路由的路径部分并没有定义 <code>:id</code>。</p><p translation-origin="off">The <code>id</code> value appears in the URL as (<code>;id=15;foo=foo</code>), not in the URL path. The path for the "Heroes" route doesn't have an <code>:id</code> token.</p><p translation-result="on">可选的路由参数没有使用“？”和“&amp;”符号分隔，因为它们将用在 URL 查询字符串中。 它们是<strong>用“;”分隔的</strong>。 这是<em>矩阵 URL</em>标记法 —— 你以前可能从未见过。</p><p translation-origin="off">The optional route parameters are not separated by "?" and "&amp;" as they would be in the URL query string. They are <strong>separated by semicolons ";"</strong> This is <em>matrix URL</em> notation—something you may not have seen before.</p><div class="alert is-helpful"><p translation-result="on"><em>Matrix URL</em>写法首次提出是在<a href="http://www.w3.org/DesignIssues/MatrixURIs.html">1996 提案</a>中，提出者是 Web 的奠基人：Tim Berners-Lee。</p><p translation-origin="off"><em>Matrix URL</em> notation is an idea first introduced in a <a href="http://www.w3.org/DesignIssues/MatrixURIs.html">1996 proposal</a> by the founder of the web, Tim Berners-Lee.</p><p translation-result="on">虽然 Matrix 写法未曾进入过 HTML 标准，但它是合法的。而且在浏览器的路由系统中，它作为从父路由和子路由中单独隔离出参数的方式而广受欢迎。Angular 的路由器正是这样一个路由系统，并支持跨浏览器的 Matrix 写法。</p><p translation-origin="off">Although matrix notation never made it into the HTML standard, it is legal and it became popular among browser routing systems as a way to isolate parameters belonging to parent and child routes. The Router is such a system and provides support for the matrix notation across browsers.</p><p translation-result="on">这种语法对你来说可能有点奇怪，不过用户不会在意这一点，因为该 URL 可以正常的通过邮件发出去或粘贴到浏览器的地址栏中。</p><p translation-origin="off">The syntax may seem strange to you but users are unlikely to notice or care as long as the URL can be emailed and pasted into a browser address bar as this one can.</p></div><a id="route-parameters-activated-route"></a><h3 id="route-parameters-in-the-activatedroute-service" translation-result="on"><em>ActivatedRoute</em> 服务中的路由参数<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters-in-the-activatedroute-service"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="route-parameters-in-the-activatedroute-service">Route parameters in the <em>ActivatedRoute</em> service<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#route-parameters-in-the-activatedroute-service"><i class="material-icons">link</i></a></h3><p translation-result="on">英雄列表仍没有改变，没有哪个英雄列被加亮显示。</p><p translation-origin="off">The list of heroes is unchanged. No hero row is highlighted.</p><div class="alert is-helpful"><p translation-result="on"><live-example ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="现场演练" href="generated/live-examples/router/stackblitz.html">现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example><em>高亮了</em>选中的行，因为它演示的是应用的最终状态，因此包含了你<em>即将</em>接触到的步骤。 此刻，本文描述的仍是那些步骤<em>之前</em>的状态。</p><p translation-origin="off">The<live-example ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="现场演练" href="generated/live-examples/router/stackblitz.html">现场演练</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example><em>does</em> highlight the selected row because it demonstrates the final state of the application which includes the steps you're <em>about</em> to cover. At the moment this guide is describing the state of affairs <em>prior</em> to those steps.</p></div><p translation-result="on"><code>HeroListComponent</code> 还完全不需要任何参数，也不知道该怎么处理它们。你可以改变这一点。</p><p translation-origin="off">The <code>HeroListComponent</code> isn't expecting any parameters at all and wouldn't know what to do with them. You can change that.</p><p translation-result="on">以前，当从 <code>HeroListComponent</code> 导航到 <code>HeroDetailComponent</code> 时，你通过 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 服务订阅了路由参数这个 <code>Observable</code>，并让它能用在 <code>HeroDetailComponent</code> 中。 你把该服务注入到了 <code>HeroDetailComponent</code> 的构造函数中。</p><p translation-origin="off">Previously, when navigating from the <code>HeroListComponent</code> to the <code>HeroDetailComponent</code>, you subscribed to the route parameter map <code>Observable</code> and made it available to the <code>HeroDetailComponent</code> in the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> service. You injected that service in the constructor of the <code>HeroDetailComponent</code>.</p><p translation-result="on">这次，你要进行反向导航，从 <code>HeroDetailComponent</code> 到 <code>HeroListComponent</code>。</p><p translation-origin="off">This time you'll be navigating in the opposite direction, from the <code>HeroDetailComponent</code> to the <code>HeroListComponent</code>.</p><p translation-result="on">首先，你扩展该路由的导入语句，以包含进 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 服务的类；</p><p translation-origin="off">First you extend the router import statement to include the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> service symbol:</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.ts" header="src/app/heroes/hero-list/hero-list.component.ts (import)" region="import-router" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> } from '@angular/router';</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.ts (import)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.ts (import)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span></code>
    </pre></aio-code></code-example><p translation-result="on">导入 <code>switchMap</code> 操作符，在路由参数的 <code>Observable</code> 对象上执行操作。</p><p translation-origin="off">Import the <code>switchMap</code> operator to perform an operation on the <code>Observable</code> of route parameter map.</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.ts" header="src/app/heroes/hero-list/hero-list.component.ts (rxjs imports)" region="rxjs-imports" ng-version="9.0.0-rc.11"><div style="display:none">import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators';</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.ts (rxjs imports)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.ts (rxjs imports)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> switchMap </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span></code>
    </pre></aio-code></code-example><p translation-result="on">接着，你注入 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 到 <code>HeroListComponent</code> 的构造函数中。</p><p translation-origin="off">Then you inject the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> in the <code>HeroListComponent</code> constructor.</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.ts" header="src/app/heroes/hero-list/hero-list.component.ts (constructor and ngOnInit)" region="ctor" ng-version="9.0.0-rc.11"><div style="display:none">export class HeroListComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { heroes$: Observable&lt;Hero[]&gt;; selectedId: number; constructor( private service: HeroService, private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> ) {} ngOnInit() { this.heroes$ = this.route.paramMap.pipe( switchMap(params =&gt; { // (+) before `params.get()` turns the string into a number this.selectedId = +params.get('id'); return this.service.getHeroes(); }) ); } }</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.ts (constructor and ngOnInit)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.ts (constructor and ngOnInit)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/core/OnInit" class="code-anchor"><span class="typ">OnInit</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  heroes$</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">&lt;</span><span class="typ">Hero</span><span class="pun">[]&gt;;</span><span class="pln">
  selectedId</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> service</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroService</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pln">
  </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">heroes$ </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route</span><span class="pun">.</span><span class="pln">paramMap</span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">
      switchMap</span><span class="pun">(</span><span class="kwd">params</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (+) before `params.get()` turns the string into a number</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">selectedId </span><span class="pun">=</span><span class="pln"> </span><span class="pun">+</span><span class="kwd">params</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">service</span><span class="pun">.</span><span class="pln">getHeroes</span><span class="pun">();</span><span class="pln">
      </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">ActivatedRoute.paramMap 属性是一个路由参数的可观察对象。当用户导航到这个组件时，paramMap 会发射一个新值，其中包含 <code>id</code>。 在 ngOnInit 中，你订阅了这些值，设置到 selectedId，并获取英雄数据。</p><p translation-origin="off">The <code><a href="api/router/ActivatedRoute#paramMap" class="code-anchor">ActivatedRoute.paramMap</a></code> property is an <code>Observable</code> map of route parameters. The <code>paramMap</code> emits a new map of values that includes <code>id</code> when the user navigates to the component. In <code>ngOnInit</code> you subscribe to those values, set the <code>selectedId</code>, and get the heroes.</p><p translation-result="on">用 <a href="guide/template-syntax#class-binding">CSS 类绑定</a>更新模板，把它绑定到 <code>isSelected</code> 方法上。 如果该方法返回 <code>true</code>，此绑定就会添加 CSS 类 <code>selected</code>，否则就移除它。 在 <code>&lt;li&gt;</code> 标记中找到它，就像这样：</p><p translation-origin="off">Update the template with a <a href="guide/template-syntax#class-binding">class binding</a>. The binding adds the <code>selected</code> CSS class when the comparison returns <code>true</code> and removes it when <code>false</code>. Look for it within the repeated <code>&lt;li&gt;</code> tag as shown here:</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.html" header="src/app/heroes/hero-list/hero-list.component.html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;ul class="heroes"&gt; &lt;li *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let hero of heroes$ | <a href="api/core/testing/async" class="code-anchor">async</a>" [class.selected]="hero.id === selectedId"&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/hero', hero.id]"&gt; &lt;span class="badge"&gt;{{ hero.id }}&lt;/span&gt;{{ hero.name }} &lt;/a&gt; &lt;/li&gt; &lt;/ul&gt; &lt;button <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/sidekicks"&gt;Go to sidekicks&lt;/button&gt;</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.html</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h2&gt;</span><span class="pln">HEROES</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
</span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"heroes"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;li</span><span class="pln"> *</span><a href="api/common/NgForOf" class="code-anchor"><span class="atn">ngFor</span></a><span class="pun">=</span><span class="atv">"let hero of heroes$ | </span><a href="api/core/testing/async" class="code-anchor"><span class="atv">async</span></a><span class="atv">"</span><span class="pln">
    [</span><span class="atn">class</span><span class="pln">.</span><span class="atn">selected</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"hero.id === selectedId"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/hero', hero.id]"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"badge"</span><span class="tag">&gt;</span><span class="pln">{{ hero.id }}</span><span class="tag">&lt;/span&gt;</span><span class="pln">{{ hero.name }}
    </span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span><span class="pln">

</span><span class="tag">&lt;button</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/sidekicks"</span><span class="tag">&gt;</span><span class="pln">Go to sidekicks</span><span class="tag">&lt;/button&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">当选中列表条目时，要添加一些样式。</p><p translation-origin="off">Add some styles to apply when the list item is selected.</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.css" region="selected" header="src/app/heroes/hero-list/hero-list.component.css" ng-version="9.0.0-rc.11"><div style="display:none">.heroes li.selected { background-color: #CFD8DC; color: white; } .heroes li.selected:hover { background-color: #BBD8DC; }</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.css</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.css">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">.</span><span class="pln">heroes li</span><span class="pun">.</span><span class="pln">selected </span><span class="pun">{</span><span class="pln">
  background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#CFD8DC;</span><span class="pln">
  color</span><span class="pun">:</span><span class="pln"> white</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">.</span><span class="pln">heroes li</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">:</span><span class="pln">hover </span><span class="pun">{</span><span class="pln">
  background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#BBD8DC;</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">当用户从英雄列表导航到英雄“Magneta”并返回时，“Magneta”看起来是选中的：</p><p translation-origin="off">When the user navigates from the heroes list to the "Magneta" hero and back, "Magneta" appears selected:</p><div class="lightbox"><img src="generated/images/guide/router/selected-hero.png" alt="Selected List" width="336" height="110"></div><p translation-result="on">这儿可选的 <code>foo</code> 路由参数人畜无害，并继续被忽略。</p><p translation-origin="off">The optional <code>foo</code> route parameter is harmless and continues to be ignored.</p><h3 id="adding-routable-animations" translation-result="on">添加路由动画<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#adding-routable-animations"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="adding-routable-animations">Adding routable animations<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#adding-routable-animations"><i class="material-icons">link</i></a></h3><a id="route-animation"></a><h4 id="adding-animations-to-the-routed-component" translation-result="on">为路由组件添加动画<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#adding-animations-to-the-routed-component"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="adding-animations-to-the-routed-component">Adding animations to the routed component<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#adding-animations-to-the-routed-component"><i class="material-icons">link</i></a></h4><p translation-result="on">这个“英雄”特性模块就要完成了，但这个特性还没有平滑的转场效果。</p><p translation-origin="off">The heroes feature module is almost complete, but what is a feature without some smooth transitions?</p><p translation-result="on">在这一节，你将为<em>英雄详情</em>组件添加一些<a href="guide/animations">动画</a>。</p><p translation-origin="off">This section shows you how to add some <a href="guide/animations">animations</a> to the <code>HeroDetailComponent</code>.</p><p translation-result="on">首先导入 <code><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a></code>，并添加到 <code>imports</code> 数组中：</p><p translation-origin="off">First import the <code><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a></code> and add it to the <code>imports</code> array:</p><code-example path="router/src/app/app.module.ts" header="src/app/app.module.ts (animations-module)" region="animations-module" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a>, ], })</div><header class="ng-star-inserted">src/app/app.module.ts (animations-module)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (animations-module)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser/animations'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pun">,</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
</span><span class="pun">})</span></code>
    </pre></aio-code></code-example><p translation-result="on">接下来，为指向 <code>HeroListComponent</code> 和 <code>HeroDetailComponent</code> 的路由定义添加一个 <code>data</code> 对象。 转场是基于 <code>states</code> 的，你将使用来自路由的 <code><a href="api/animations/animation" class="code-anchor">animation</a></code> 数据为转场提供一个有名字的动画 <code><a href="api/animations/state" class="code-anchor">state</a></code>。</p><p translation-origin="off">Next, add a <code>data</code> object to the routes for <code>HeroListComponent</code> and <code>HeroDetailComponent</code>. Transitions are based on <code>states</code> and you'll use the <code><a href="api/animations/animation" class="code-anchor">animation</a></code> data from the route to provide a named animation <code><a href="api/animations/state" class="code-anchor">state</a></code> for the transitions.</p><code-example path="router/src/app/heroes/heroes-routing.module.2.ts" header="src/app/heroes/heroes-routing.module.ts (animation data)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; const heroesRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'heroes', component: HeroListComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'heroes' } }, { path: 'hero/:id', component: HeroDetailComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'hero' } } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(heroesRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class HeroesRoutingModule { }</div><header class="ng-star-inserted">src/app/heroes/heroes-routing.module.ts (animation data)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes-routing.module.ts (animation data)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-detail/hero-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> heroesRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln">  component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/animations/animation" class="code-anchor"><span class="pln">animation</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/animations/animation" class="code-anchor"><span class="pln">animation</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">heroesRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroesRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">在根目录 <code>src/app/</code> 下创建一个 <code>animations.ts</code>。内容如下：</p><p translation-origin="off">Create an <code>animations.ts</code> file in the root <code>src/app/</code> folder. The contents look like this:</p><code-example path="router/src/app/animations.ts" header="src/app/animations.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/animations/trigger" class="code-anchor">trigger</a>, <a href="api/animations/animateChild" class="code-anchor">animateChild</a>, group, <a href="api/animations/transition" class="code-anchor">transition</a>, <a href="api/animations/animate" class="code-anchor">animate</a>, <a href="api/animations/style" class="code-anchor">style</a>, <a href="api/animations/query" class="code-anchor">query</a> } from '@angular/animations'; // Routable animations export const slideInAnimation = <a href="api/animations/trigger" class="code-anchor">trigger</a>('routeAnimation', [ <a href="api/animations/transition" class="code-anchor">transition</a>('heroes &lt;=&gt; hero', [ <a href="api/animations/style" class="code-anchor">style</a>({ <a href="api/router/Scroll#position" class="code-anchor">position</a>: 'relative' }), <a href="api/animations/query" class="code-anchor">query</a>(':enter, :leave', [ <a href="api/animations/style" class="code-anchor">style</a>({ <a href="api/router/Scroll#position" class="code-anchor">position</a>: 'absolute', top: 0, left: 0, width: '100%' }) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', [ <a href="api/animations/style" class="code-anchor">style</a>({ left: '-100%'}) ]), <a href="api/animations/query" class="code-anchor">query</a>(':leave', <a href="api/animations/animateChild" class="code-anchor">animateChild</a>()), group([ <a href="api/animations/query" class="code-anchor">query</a>(':leave', [ <a href="api/animations/animate" class="code-anchor">animate</a>('300ms ease-out', <a href="api/animations/style" class="code-anchor">style</a>({ left: '100%'})) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', [ <a href="api/animations/animate" class="code-anchor">animate</a>('300ms ease-out', <a href="api/animations/style" class="code-anchor">style</a>({ left: '0%'})) ]) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', <a href="api/animations/animateChild" class="code-anchor">animateChild</a>()), ]) ]);</div><header class="ng-star-inserted">src/app/animations.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/animations.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/animations/trigger" class="code-anchor"><span class="pln">trigger</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">,</span><span class="pln"> </span><span class="kwd">group</span><span class="pun">,</span><span class="pln">
  </span><a href="api/animations/transition" class="code-anchor"><span class="pln">transition</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/animations'</span><span class="pun">;</span><span class="pln">


</span><span class="com">// Routable animations</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> slideInAnimation </span><span class="pun">=</span><span class="pln">
  </span><a href="api/animations/trigger" class="code-anchor"><span class="pln">trigger</span></a><span class="pun">(</span><span class="str">'routeAnimation'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/animations/transition" class="code-anchor"><span class="pln">transition</span></a><span class="pun">(</span><span class="str">'heroes &lt;=&gt; hero'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> </span><a href="api/router/Scroll#position" class="code-anchor"><span class="pln">position</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'relative'</span><span class="pln"> </span><span class="pun">}),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter, :leave'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln">
          </span><a href="api/router/Scroll#position" class="code-anchor"><span class="pln">position</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'absolute'</span><span class="pun">,</span><span class="pln">
          top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
          left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
          width</span><span class="pun">:</span><span class="pln"> </span><span class="str">'100%'</span><span class="pln">
        </span><span class="pun">})</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'-100%'</span><span class="pun">})</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':leave'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">()),</span><span class="pln">
      </span><span class="kwd">group</span><span class="pun">([</span><span class="pln">
        </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':leave'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">(</span><span class="str">'300ms ease-out'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'100%'</span><span class="pun">}))</span><span class="pln">
        </span><span class="pun">]),</span><span class="pln">
        </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">(</span><span class="str">'300ms ease-out'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'0%'</span><span class="pun">}))</span><span class="pln">
        </span><span class="pun">])</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">()),</span><span class="pln">
    </span><span class="pun">])</span><span class="pln">
  </span><span class="pun">]);</span></code>
    </pre></aio-code></code-example><p translation-result="on">该文件做了如下工作：</p><p translation-origin="off">This file does the following:</p><ul><li><p translation-result="on">导入动画符号以构建动画触发器、控制状态并管理状态之间的过渡。</p><p translation-origin="off">Imports the animation symbols that build the animation triggers, control state, and manage transitions between states.</p></li><li><p translation-result="on">导出了一个名叫 <code>slideInAnimation</code> 的常量，并把它设置为一个名叫*<code>routeAnimation</code> 的动画触发器。</p><p translation-origin="off">Exports a constant named <code>slideInAnimation</code> set to an animation trigger named <em><code>routeAnimation</code></em>;</p></li><li><p translation-result="on">定义一个<em>转场动画</em>，当在 <code>heroes</code> 和 <code>hero</code> 路由之间来回切换时，如果进入（<code>:enter</code>）应用视图则让组件从屏幕的左侧滑入，如果离开（<code>:leave</code>）应用视图则让组件从右侧划出。</p><p translation-origin="off">Defines one <em>transition</em> when switching back and forth from the <code>heroes</code> and <code>hero</code> routes to ease the component in from the left of the screen as it enters the application view (<code>:enter</code>), the other to animate the component to the right as it leaves the application view (<code>:leave</code>).</p></li></ul><p translation-result="on">你还可以为其它路由组件用不同的转场效果创建更多触发器。现在这个触发器已经足够当前的里程碑用了。</p><p translation-origin="off">You could also create more transitions for other routes. This trigger is sufficient for the current milestone.</p><p translation-result="on">回到 <code>AppComponent</code>，从 <code>@angular/router</code> 中导入 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 令牌，并从 <code>'./animations.ts</code> 中导入 <code>slideInDownAnimation</code>。</p><p translation-origin="off">Back in the <code>AppComponent</code>, import the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> token from the <code>@angular/router</code> package and the <code>slideInAnimation</code> from <code>'./animations.ts</code>.</p><p translation-result="on">把一个包含 <code>slideInDownAnimation</code> 的 <code>animations</code> 数组添加到 <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> 的元数据中。</p><p translation-origin="off">Add an <code>animations</code> array to the <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> metadata's that contains the <code>slideInAnimation</code>.</p><code-example path="router/src/app/app.component.2.ts" header="src/app/app.component.ts (animations)" region="animation-imports" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a> } from '@angular/router'; import { slideInAnimation } from './animations'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-root', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: 'app.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['app.component.css'], animations: [ slideInAnimation ] })</div><header class="ng-star-inserted">src/app/app.component.ts (animations)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (animations)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterOutlet" class="code-anchor"><span class="typ">RouterOutlet</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> slideInAnimation </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./animations'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Component" class="code-anchor"><span class="lit">Component</span></a><span class="pun">({</span><span class="pln">
  selector</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app-root'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#templateUrl" class="code-anchor"><span class="pln">templateUrl</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'app.component.html'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#styleUrls" class="code-anchor"><span class="pln">styleUrls</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'app.component.css'</span><span class="pun">],</span><span class="pln">
  animations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> slideInAnimation </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span></code>
    </pre></aio-code></code-example><p translation-result="on">为了使用路由动画，你需要把 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 包装到一个元素中。你要把 <code>@routeAnimation</code> 触发器绑定到该元素上。</p><p translation-origin="off">In order to use the routable animations, you'll need to wrap the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> inside an element. You'll use the <code>@routeAnimation</code> trigger and bind it to the element.</p><p translation-result="on">为了把 <code>@routeAnimation</code> 转场转场到指定的状态，你需要从 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 的 <code>data</code> 中提供它。 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 导出成了一个模板变量 <code>outlet</code>，这样你就可以绑定一个到路由出口的引用了。给这个变量取名做 <code>routerOutlet</code> 是一个理想的选择。</p><p translation-origin="off">For the <code>@routeAnimation</code> transitions to key off states, you'll need to provide it with the <code>data</code> from the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>. The <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> is exposed as an <code>outlet</code> template variable, so you bind a reference to the router outlet. A variable of <code>routerOutlet</code> is an ideal choice.</p><code-example path="router/src/app/app.component.2.html" header="src/app/app.component.html (router outlet)" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h1&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;/nav&gt; &lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/app.component.html (router outlet)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html (router outlet)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> [@</span><span class="atn">routeAnimation</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"getAnimationData(routerOutlet)"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> #</span><span class="atn">routerOutlet</span><span class="pun">=</span><span class="atv">"outlet"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>@routeAnimation</code> 属性使用所提供的 <code>routerOutlet</code> 引用来绑定到 <code>getAnimationData</code>，因此你需要在 <code>AppComponent</code> 中定义那个函数。<code>getAnimationData</code> 函数会根据 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 所提供的 <code>data</code> 对象返回动画的属性。<code><a href="api/animations/animation" class="code-anchor">animation</a></code> 属性会根据你在 <code>animations.ts</code> 中定义 <code>slideInAnimation</code> 时使用的 <code><a href="api/animations/transition" class="code-anchor">transition</a></code> 名称进行匹配。</p><p translation-origin="off">The <code>@routeAnimation</code> property is bound to the <code>getAnimationData</code> with the provided <code>routerOutlet</code> reference, so you'll need to define that function in the <code>AppComponent</code>. The <code>getAnimationData</code> function returns the animation property from the <code>data</code> provided through the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>. The <code><a href="api/animations/animation" class="code-anchor">animation</a></code> property matches the <code><a href="api/animations/transition" class="code-anchor">transition</a></code> names you used in the <code>slideInAnimation</code> defined in <code>animations.ts</code>.</p><code-example path="router/src/app/app.component.2.ts" header="src/app/app.component.ts (router outlet)" region="function-binding" ng-version="9.0.0-rc.11"><div style="display:none">export class AppComponent { getAnimationData(outlet: <a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a>) { return outlet &amp;&amp; outlet.activatedRouteData &amp;&amp; outlet.activatedRouteData['<a href="api/animations/animation" class="code-anchor">animation</a>']; } }</div><header class="ng-star-inserted">src/app/app.component.ts (router outlet)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (router outlet)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  getAnimationData</span><span class="pun">(</span><span class="pln">outlet</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterOutlet" class="code-anchor"><span class="typ">RouterOutlet</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> outlet </span><span class="pun">&amp;&amp;</span><span class="pln"> outlet</span><span class="pun">.</span><span class="pln">activatedRouteData </span><span class="pun">&amp;&amp;</span><span class="pln"> outlet</span><span class="pun">.</span><span class="pln">activatedRouteData</span><span class="pun">[</span><span class="str">'</span><a href="api/animations/animation" class="code-anchor"><span class="str">animation</span></a><span class="str">'</span><span class="pun">];</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">如果在两个路由之间切换，导航进来时，<code>HeroDetailComponent</code> 和 <code>HeroListComponent</code> 会从左侧滑入；导航离开时将会从右侧划出。</p><p translation-origin="off">When switching between the two routes, the <code>HeroDetailComponent</code> and <code>HeroListComponent</code> will ease in from the left when routed to and will slide to the right when navigating away.</p><a id="milestone-3-wrap-up"></a><h3 id="milestone-3-wrap-up" translation-result="on">里程碑 3 的总结<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-3-wrap-up"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="milestone-3-wrap-up">Milestone 3 wrap up<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-3-wrap-up"><i class="material-icons">link</i></a></h3><p translation-result="on">你学到了如何：</p><p translation-origin="off">You've learned how to do the following:</p><ul><li><p translation-result="on">把应用组织成<em>特性区</em></p><p translation-origin="off">Organize the app into <em>feature areas</em>.</p></li><li><p translation-result="on">命令式的从一个组件导航到另一个</p><p translation-origin="off">Navigate imperatively from one component to another.</p></li><li><p translation-result="on">通过路由参数传递信息，并在组件中订阅它们</p><p translation-origin="off">Pass information along in route parameters and subscribe to them in the component.</p></li><li><p translation-result="on">把这个特性分区模块导入根模块 <code>AppModule</code></p><p translation-origin="off">Import the feature area NgModule into the <code>AppModule</code>.</p></li><li><p translation-result="on">把动画应用到路由组件上</p><p translation-origin="off">Applying routable animations based on the page.</p></li></ul><p translation-result="on">做完这些修改之后，目录结构是这样的：</p><p translation-origin="off">After these changes, the folder structure looks like this:</p><div class="filetree"><div class="file"><p>angular-router-sample</p></div><div class="children"><div class="file">src</div><div class="children"><div class="file"><p>app</p></div><div class="children"><div class="file"><p>crisis-list</p></div><div class="children"><div class="file">crisis-list.component.css</div><div class="file">crisis-list.component.html</div><div class="file">crisis-list.component.ts</div></div><div class="file"><p>heroes</p></div><div class="children"><div class="file"><p>hero-detail</p></div><div class="children"><div class="file">hero-detail.component.css</div><div class="file">hero-detail.component.html</div><div class="file">hero-detail.component.ts</div></div><div class="file"><p>hero-list</p></div><div class="children"><div class="file">hero-list.component.css</div><div class="file">hero-list.component.html</div><div class="file">hero-list.component.ts</div></div><div class="file"><p>hero.service.ts</p></div><div class="file">hero.ts</div><div class="file">heroes-routing.module.ts</div><div class="file"><p>heroes.module.ts</p></div><div class="file"><p>mock-heroes.ts</p></div></div><div class="file">page-not-found</div><div class="children"><div class="file"><p>page-not-found.component.css</p></div><div class="file"><p>page-not-found.component.html</p></div><div class="file"><p>page-not-found.component.ts</p></div></div></div><div class="file">animations.ts</div><div class="file">app.component.css</div><div class="file">app.component.html</div><div class="file"><p>app.component.ts</p></div><div class="file"><p>app.module.ts</p></div><div class="file"><p>app-routing.module.ts</p></div><div class="file"><p>main.ts</p></div><div class="file"><p>message.service.ts</p></div><div class="file"><p>index.html</p></div><div class="file"><p>styles.css</p></div><div class="file"><p>tsconfig.json</p></div></div><div class="file"><p>node_modules ...</p></div><div class="file"><p>package.json</p></div></div></div><p translation-result="on">这里是当前版本的范例程序相关文件。</p><p translation-origin="off">Here are the relevant files for this version of the sample application.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="animations.ts" path="router/src/app/animations.ts">import { <a href="api/animations/trigger" class="code-anchor">trigger</a>, <a href="api/animations/animateChild" class="code-anchor">animateChild</a>, group, <a href="api/animations/transition" class="code-anchor">transition</a>, <a href="api/animations/animate" class="code-anchor">animate</a>, <a href="api/animations/style" class="code-anchor">style</a>, <a href="api/animations/query" class="code-anchor">query</a> } from '@angular/animations'; // Routable animations export const slideInAnimation = <a href="api/animations/trigger" class="code-anchor">trigger</a>('routeAnimation', [ <a href="api/animations/transition" class="code-anchor">transition</a>('heroes &lt;=&gt; hero', [ <a href="api/animations/style" class="code-anchor">style</a>({ <a href="api/router/Scroll#position" class="code-anchor">position</a>: 'relative' }), <a href="api/animations/query" class="code-anchor">query</a>(':enter, :leave', [ <a href="api/animations/style" class="code-anchor">style</a>({ <a href="api/router/Scroll#position" class="code-anchor">position</a>: 'absolute', top: 0, left: 0, width: '100%' }) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', [ <a href="api/animations/style" class="code-anchor">style</a>({ left: '-100%'}) ]), <a href="api/animations/query" class="code-anchor">query</a>(':leave', <a href="api/animations/animateChild" class="code-anchor">animateChild</a>()), group([ <a href="api/animations/query" class="code-anchor">query</a>(':leave', [ <a href="api/animations/animate" class="code-anchor">animate</a>('300ms ease-out', <a href="api/animations/style" class="code-anchor">style</a>({ left: '100%'})) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', [ <a href="api/animations/animate" class="code-anchor">animate</a>('300ms ease-out', <a href="api/animations/style" class="code-anchor">style</a>({ left: '0%'})) ]) ]), <a href="api/animations/query" class="code-anchor">query</a>(':enter', <a href="api/animations/animateChild" class="code-anchor">animateChild</a>()), ]) ]);</code-pane><code-pane header="app.component.html" path="router/src/app/app.component.2.html">&lt;h1&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;/nav&gt; &lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt;</code-pane><code-pane header="app.component.ts" path="router/src/app/app.component.2.ts">import { <a href="api/core/Component" class="code-anchor">Component</a> } from '@angular/core'; import { <a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a> } from '@angular/router'; import { slideInAnimation } from './animations'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-root', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: 'app.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['app.component.css'], animations: [ slideInAnimation ] }) export class AppComponent { getAnimationData(outlet: <a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a>) { return outlet &amp;&amp; outlet.activatedRouteData &amp;&amp; outlet.activatedRouteData['<a href="api/animations/animation" class="code-anchor">animation</a>']; } }</code-pane><code-pane header="app.module.ts" path="router/src/app/app.module.3.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, AppRoutingModule ], declarations: [ AppComponent, CrisisListComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</code-pane><code-pane header="app-routing.module.ts" path="router/src/app/app-routing.module.2.ts" region="milestone3">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; /* . . . */ import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisListComponent }, /* . . . */ { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule {}</code-pane><code-pane header="hero-list.component.css" path="router/src/app/heroes/hero-list/hero-list.component.css">/* HeroListComponent's private CSS styles */ .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; } .heroes li { <a href="api/router/Scroll#position" class="code-anchor">position</a>: relative; cursor: pointer; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px; } .heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em; } .heroes a { color: #888; text-decoration: none; <a href="api/router/Scroll#position" class="code-anchor">position</a>: relative; display: block; } .heroes a:hover { color:#607D8B; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; <a href="api/router/Scroll#position" class="code-anchor">position</a>: relative; left: -1px; top: -4px; height: 1.8em; min-width: 16px; text-align: right; margin-right: .8em; border-radius: 4px 0 0 4px; } button { background-color: #eee; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; cursor: hand; font-family: Arial; } button:hover { background-color: #cfd8dc; } button.delete { <a href="api/router/Scroll#position" class="code-anchor">position</a>: relative; left: 194px; top: -32px; background-color: gray !important; color: white; } .heroes li.selected { background-color: #CFD8DC; color: white; } .heroes li.selected:hover { background-color: #BBD8DC; }</code-pane><code-pane header="hero-list.component.html" path="router/src/app/heroes/hero-list/hero-list.component.html">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;ul class="heroes"&gt; &lt;li *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let hero of heroes$ | <a href="api/core/testing/async" class="code-anchor">async</a>" [class.selected]="hero.id === selectedId"&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/hero', hero.id]"&gt; &lt;span class="badge"&gt;{{ hero.id }}&lt;/span&gt;{{ hero.name }} &lt;/a&gt; &lt;/li&gt; &lt;/ul&gt; &lt;button <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/sidekicks"&gt;Go to sidekicks&lt;/button&gt;</code-pane><code-pane header="hero-list.component.ts" path="router/src/app/heroes/hero-list/hero-list.component.ts">// TODO: Feature Componetized like CrisisCenter import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a> } from '@angular/core'; import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> } from '@angular/router'; import { HeroService } from '../hero.service'; import { Hero } from '../hero'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-hero-list', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './hero-list.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./hero-list.component.css'] }) export class HeroListComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { heroes$: Observable&lt;Hero[]&gt;; selectedId: number; constructor( private service: HeroService, private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> ) {} ngOnInit() { this.heroes$ = this.route.paramMap.pipe( switchMap(params =&gt; { // (+) before `params.get()` turns the string into a number this.selectedId = +params.get('id'); return this.service.getHeroes(); }) ); } }</code-pane><code-pane header="hero-detail.component.html" path="router/src/app/heroes/hero-detail/hero-detail.component.html">&lt;h2&gt;HEROES&lt;/h2&gt; &lt;div *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="hero$ | <a href="api/core/testing/async" class="code-anchor">async</a> as hero"&gt; &lt;h3&gt;"{{ hero.name }}"&lt;/h3&gt; &lt;div&gt; &lt;label&gt;Id: &lt;/label&gt;{{ hero.id }}&lt;/div&gt; &lt;div&gt; &lt;label&gt;Name: &lt;/label&gt; &lt;input [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="hero.name" placeholder="name"/&gt; &lt;/div&gt; &lt;p&gt; &lt;button (click)="gotoHeroes(hero)"&gt;Back&lt;/button&gt; &lt;/p&gt; &lt;/div&gt;</code-pane><code-pane header="hero-detail.component.ts" path="router/src/app/heroes/hero-detail/hero-detail.component.3.ts">import { switchMap } from 'rxjs/operators'; import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a> } from '@angular/core'; import { <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, <a href="api/router/ParamMap" class="code-anchor">ParamMap</a> } from '@angular/router'; import { Observable } from 'rxjs'; import { HeroService } from '../hero.service'; import { Hero } from '../hero'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-hero-detail', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './hero-detail.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./hero-detail.component.css'] }) export class HeroDetailComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { hero$: Observable&lt;Hero&gt;; constructor( private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, private router: <a href="api/router/Router" class="code-anchor">Router</a>, private service: HeroService ) {} ngOnInit() { this.hero$ = this.route.paramMap.pipe( switchMap((params: <a href="api/router/ParamMap" class="code-anchor">ParamMap</a>) =&gt; this.service.getHero(params.get('id'))) ); } gotoHeroes(hero: Hero) { let heroId = hero ? hero.id : null; // Pass along the hero id if available // so that the HeroList component can select that hero. // Include a junk 'foo' property for fun. this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]); } } /* this.router.navigate(['/superheroes', { id: heroId, foo: 'foo' }]); */</code-pane><code-pane header="hero.service.ts" path="router/src/app/heroes/hero.service.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { Hero } from './hero'; import { HEROES } from './mock-heroes'; import { MessageService } from '../message.service'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class HeroService { constructor(private messageService: MessageService) { } getHeroes(): Observable&lt;Hero[]&gt; { // TODO: send the <a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a> _after_ fetching the heroes this.messageService.add('HeroService: fetched heroes'); return of(HEROES); } getHero(id: number | string) { return this.getHeroes().pipe( // (+) before `id` turns the string into a number map((heroes: Hero[]) =&gt; heroes.find(hero =&gt; hero.id === +id)) ); } }</code-pane><code-pane header="heroes.module.ts" path="router/src/app/heroes/heroes.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; import { HeroesRoutingModule } from './heroes-routing.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesRoutingModule ], declarations: [ HeroListComponent, HeroDetailComponent ] }) export class HeroesModule {}</code-pane><code-pane header="heroes-routing.module.ts" path="router/src/app/heroes/heroes-routing.module.2.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; const heroesRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'heroes', component: HeroListComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'heroes' } }, { path: 'hero/:id', component: HeroDetailComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'hero' } } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(heroesRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class HeroesRoutingModule { }</code-pane><code-pane header="message.service.ts" path="router/src/app/message.service.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class MessageService { <a href="api/service-worker/SwPush#messages" class="code-anchor">messages</a>: string[] = []; add(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>: string) { this.messages.push(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>); } clear() { this.messages = []; } }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-2-0" tabindex="0" aria-posinset="1" aria-setsize="14" aria-controls="mat-tab-content-2-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">animations.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-1" tabindex="-1" aria-posinset="2" aria-setsize="14" aria-controls="mat-tab-content-2-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-2" tabindex="-1" aria-posinset="3" aria-setsize="14" aria-controls="mat-tab-content-2-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-3" tabindex="-1" aria-posinset="4" aria-setsize="14" aria-controls="mat-tab-content-2-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-4" tabindex="-1" aria-posinset="5" aria-setsize="14" aria-controls="mat-tab-content-2-4" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app-routing.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-5" tabindex="-1" aria-posinset="6" aria-setsize="14" aria-controls="mat-tab-content-2-5" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-list.component.css</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-6" tabindex="-1" aria-posinset="7" aria-setsize="14" aria-controls="mat-tab-content-2-6" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-list.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-7" tabindex="-1" aria-posinset="8" aria-setsize="14" aria-controls="mat-tab-content-2-7" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-list.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-8" tabindex="-1" aria-posinset="9" aria-setsize="14" aria-controls="mat-tab-content-2-8" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-detail.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-9" tabindex="-1" aria-posinset="10" aria-setsize="14" aria-controls="mat-tab-content-2-9" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-detail.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-10" tabindex="-1" aria-posinset="11" aria-setsize="14" aria-controls="mat-tab-content-2-10" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero.service.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-11" tabindex="-1" aria-posinset="12" aria-setsize="14" aria-controls="mat-tab-content-2-11" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">heroes.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-12" tabindex="-1" aria-posinset="13" aria-setsize="14" aria-controls="mat-tab-content-2-12" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">heroes-routing.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-2-13" tabindex="-1" aria-posinset="14" aria-setsize="14" aria-controls="mat-tab-content-2-13" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">message.service.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:160px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-10 mat-tab-body-active ng-star-inserted" id="mat-tab-content-2-0" aria-labelledby="mat-tab-label-2-0"><div class="mat-tab-body-content ng-tns-c50-10 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from animations.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/animations/trigger" class="code-anchor"><span class="pln">trigger</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">,</span><span class="pln"> </span><span class="kwd">group</span><span class="pun">,</span><span class="pln">
  </span><a href="api/animations/transition" class="code-anchor"><span class="pln">transition</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/animations'</span><span class="pun">;</span><span class="pln">


</span><span class="com">// Routable animations</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> slideInAnimation </span><span class="pun">=</span><span class="pln">
  </span><a href="api/animations/trigger" class="code-anchor"><span class="pln">trigger</span></a><span class="pun">(</span><span class="str">'routeAnimation'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/animations/transition" class="code-anchor"><span class="pln">transition</span></a><span class="pun">(</span><span class="str">'heroes &lt;=&gt; hero'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> </span><a href="api/router/Scroll#position" class="code-anchor"><span class="pln">position</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'relative'</span><span class="pln"> </span><span class="pun">}),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter, :leave'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln">
          </span><a href="api/router/Scroll#position" class="code-anchor"><span class="pln">position</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'absolute'</span><span class="pun">,</span><span class="pln">
          top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
          left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
          width</span><span class="pun">:</span><span class="pln"> </span><span class="str">'100%'</span><span class="pln">
        </span><span class="pun">})</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'-100%'</span><span class="pun">})</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':leave'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">()),</span><span class="pln">
      </span><span class="kwd">group</span><span class="pun">([</span><span class="pln">
        </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':leave'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">(</span><span class="str">'300ms ease-out'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'100%'</span><span class="pun">}))</span><span class="pln">
        </span><span class="pun">]),</span><span class="pln">
        </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><a href="api/animations/animate" class="code-anchor"><span class="pln">animate</span></a><span class="pun">(</span><span class="str">'300ms ease-out'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/style" class="code-anchor"><span class="pln">style</span></a><span class="pun">({</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'0%'</span><span class="pun">}))</span><span class="pln">
        </span><span class="pun">])</span><span class="pln">
      </span><span class="pun">]),</span><span class="pln">
      </span><a href="api/animations/query" class="code-anchor"><span class="pln">query</span></a><span class="pun">(</span><span class="str">':enter'</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/animateChild" class="code-anchor"><span class="pln">animateChild</span></a><span class="pun">()),</span><span class="pln">
    </span><span class="pun">])</span><span class="pln">
  </span><span class="pun">]);</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-11 ng-star-inserted" id="mat-tab-content-2-1" aria-labelledby="mat-tab-label-2-1"><div class="mat-tab-body-content ng-tns-c50-11 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-12 ng-star-inserted" id="mat-tab-content-2-2" aria-labelledby="mat-tab-label-2-2"><div class="mat-tab-body-content ng-tns-c50-12 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-13 ng-star-inserted" id="mat-tab-content-2-3" aria-labelledby="mat-tab-label-2-3"><div class="mat-tab-body-content ng-tns-c50-13 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-14 ng-star-inserted" id="mat-tab-content-2-4" aria-labelledby="mat-tab-label-2-4"><div class="mat-tab-body-content ng-tns-c50-14 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-15 ng-star-inserted" id="mat-tab-content-2-5" aria-labelledby="mat-tab-label-2-5"><div class="mat-tab-body-content ng-tns-c50-15 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-16 ng-star-inserted" id="mat-tab-content-2-6" aria-labelledby="mat-tab-label-2-6"><div class="mat-tab-body-content ng-tns-c50-16 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-17 ng-star-inserted" id="mat-tab-content-2-7" aria-labelledby="mat-tab-label-2-7"><div class="mat-tab-body-content ng-tns-c50-17 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-18 ng-star-inserted" id="mat-tab-content-2-8" aria-labelledby="mat-tab-label-2-8"><div class="mat-tab-body-content ng-tns-c50-18 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-19 ng-star-inserted" id="mat-tab-content-2-9" aria-labelledby="mat-tab-label-2-9"><div class="mat-tab-body-content ng-tns-c50-19 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-20 ng-star-inserted" id="mat-tab-content-2-10" aria-labelledby="mat-tab-label-2-10"><div class="mat-tab-body-content ng-tns-c50-20 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-21 ng-star-inserted" id="mat-tab-content-2-11" aria-labelledby="mat-tab-label-2-11"><div class="mat-tab-body-content ng-tns-c50-21 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-22 ng-star-inserted" id="mat-tab-content-2-12" aria-labelledby="mat-tab-label-2-12"><div class="mat-tab-body-content ng-tns-c50-22 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-23 ng-star-inserted" id="mat-tab-content-2-13" aria-labelledby="mat-tab-label-2-13"><div class="mat-tab-body-content ng-tns-c50-23 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><a id="milestone-4"></a><h2 id="milestone-4-crisis-center-feature" translation-result="on">里程碑 4：危机中心<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-4-crisis-center-feature"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-4-crisis-center-feature">Milestone 4: Crisis center feature<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-4-crisis-center-feature"><i class="material-icons">link</i></a></h2><p translation-result="on">是时候往该应用的危机中心（现在是占位符）中添加一些真实的特性了。</p><p translation-origin="off">It's time to add real features to the app's current placeholder crisis center.</p><p translation-result="on">先从模仿“英雄管理”中的特性开始：</p><p translation-origin="off">Begin by imitating the heroes feature:</p><ul><li><p translation-result="on">在 <code>src/app</code> 目录下创建一个 <code>crisis-center</code> 子目录。</p><p translation-origin="off">Create a <code>crisis-center</code> subfolder in the <code>src/app</code> folder.</p></li><li><p translation-result="on">把 <code>app/heroes</code> 中的文件和目录复制到新的 <code>crisis-center</code> 文件夹中。</p><p translation-origin="off">Copy the files and folders from <code>app/heroes</code> into the new <code>crisis-center</code> folder.</p></li><li><p translation-result="on">在这些新建的文件中，把每个 "hero" 都改成 "crisis"，每个 "heroes" 都改成 "crises"。</p><p translation-origin="off">In the new files, change every mention of "hero" to "crisis", and "heroes" to "crises".</p></li><li><p translation-result="on">把这些 NgModule 文件改名为 <code>crisis-center.module.ts</code> 和 <code>crisis-center-routing.module.ts</code>。</p><p translation-origin="off">Rename the NgModule files to <code>crisis-center.module.ts</code> and <code>crisis-center-routing.module.ts</code>.</p></li></ul><p translation-result="on">你还要用模拟的危机列表替换模拟的英雄列表：</p><p translation-origin="off">You'll use mock crises instead of mock heroes:</p><code-example path="router/src/app/crisis-center/mock-crises.ts" header="src/app/crisis-center/mock-crises.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { Crisis } from './crisis'; export const CRISES: Crisis[] = [ { id: 1, name: 'Dragon Burning Cities' }, { id: 2, name: 'Sky Rains Great White Sharks' }, { id: 3, name: 'Giant Asteroid Heading For Earth' }, { id: 4, name: 'Procrastinators Meeting Delayed Again' }, ]</div><header class="ng-star-inserted">src/app/crisis-center/mock-crises.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/mock-crises.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Crisis</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> CRISES</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Crisis</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Dragon Burning Cities'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Sky Rains Great White Sharks'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Giant Asteroid Heading For Earth'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Procrastinators Meeting Delayed Again'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="pun">]</span></code>
    </pre></aio-code></code-example><p translation-result="on">最终的危机中心可以作为引入<strong>子路由</strong>这个新概念的基础。 你可以把<em>英雄管理</em>保持在当前状态，以便和<em>危机中心</em>进行对比，以后再根据这些差异是否有价值来决定后续行动。</p><p translation-origin="off">The resulting crisis center is a foundation for introducing a new concept—<strong>child routing</strong>. You can leave <em>Heroes</em> in its current state as a contrast with the <em>Crisis Center</em> and decide later if the differences are worthwhile.</p><div class="alert is-helpful"><p translation-result="on">遵循<a href="https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html" target="_blank" title="Separation of Concerns"><em>关注点分离（Separation of Concerns）</em>原则</a>， 对<em>危机中心</em>的修改不会影响 <code>AppModule</code> 或其它特性模块中的组件。</p><p translation-origin="off">In keeping with the <a href="https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html" title="Separation of Concerns"><em>Separation of Concerns</em> principle</a>, changes to the <em>Crisis Center</em> won't affect the <code>AppModule</code> or any other feature's component.</p></div><a id="crisis-child-routes"></a><h3 id="a-crisis-center-with-child-routes" translation-result="on">带有子路由的危机中心<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#a-crisis-center-with-child-routes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="a-crisis-center-with-child-routes">A crisis center with child routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#a-crisis-center-with-child-routes"><i class="material-icons">link</i></a></h3><p translation-result="on">本节会展示如何组织危机中心，来满足 Angular 应用所推荐的模式：</p><p translation-origin="off">This section shows you how to organize the crisis center to conform to the following recommended pattern for Angular applications:</p><ul><li><p translation-result="on">把每个特性放在自己的目录中。</p><p translation-origin="off">Each feature area resides in its own folder.</p></li><li><p translation-result="on">每个特性都有自己的 Angular 特性模块。</p><p translation-origin="off">Each feature has its own Angular feature module.</p></li><li><p translation-result="on">每个特性区都有自己的根组件。</p><p translation-origin="off">Each area has its own area root component.</p></li><li><p translation-result="on">每个特性区的根组件中都有自己的路由出口及其子路由。</p><p translation-origin="off">Each area root component has its own router outlet and child routes.</p></li><li><p translation-result="on">特性区的路由很少（或完全不）与其它特性区的路由交叉。</p><p translation-origin="off">Feature area routes rarely (if ever) cross with routes of other features.</p></li></ul><p translation-result="on">如果你还有更多特性区，它们的组件树是这样的：</p><p translation-origin="off">If your app had many feature areas, the app component trees might look like this:</p><div class="lightbox"><img src="generated/images/guide/router/component-tree.png" alt="Component Tree" width="473" height="258"></div><a id="child-routing-component"></a><h3 id="child-routing-component" translation-result="on">子路由组件<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#child-routing-component"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="child-routing-component">Child routing component<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#child-routing-component"><i class="material-icons">link</i></a></h3><p translation-result="on">在 <code>crisis-center</code> 目录下生成一个 <code>CrisisCenter</code> 组件：</p><p translation-origin="off">Generate a <code>CrisisCenter</code> component in the <code>crisis-center</code> folder:</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component crisis-center/crisis-center</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">/</span><span class="pln">crisis</span><span class="pun">-</span><span class="pln">center</span></code>
    </pre></aio-code></code-example><p translation-result="on">把组件模板修改成这样：</p><p translation-origin="off">Update the component template to look like this:</p><code-example path="router/src/app/crisis-center/crisis-center/crisis-center.component.html" header="src/app/crisis-center/crisis-center/crisis-center.component.html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h2&gt;CRISIS CENTER&lt;/h2&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center/crisis-center.component.html</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center/crisis-center.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h2&gt;</span><span class="pln">CRISIS CENTER</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>CrisisCenterComponent</code> 和 <code>AppComponent</code> 有下列共同点：</p><p translation-origin="off">The <code>CrisisCenterComponent</code> has the following in common with the <code>AppComponent</code>:</p><ul><li><p translation-result="on">它是危机中心特性区的<em>根</em>，正如 <code>AppComponent</code> 是整个应用的根。</p><p translation-origin="off">It is the <em>root</em> of the crisis center area, just as <code>AppComponent</code> is the root of the entire application.</p></li><li><p translation-result="on">它是危机管理特性区的<em>壳</em>，正如 <code>AppComponent</code> 是管理高层工作流的壳。</p><p translation-origin="off">It is a <em>shell</em> for the crisis management feature area, just as the <code>AppComponent</code> is a shell to manage the high-level workflow.</p></li></ul><p translation-result="on">就像大多数的壳一样，<code>CrisisCenterComponent</code> 类也非常简单，甚至比 <code>AppComponent</code> 更简单： 它没有业务逻辑，它的模板中没有链接，只有一个标题和用于放置危机中心的子组件的 <code>&lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code>。</p><p translation-origin="off">Like most shells, the <code>CrisisCenterComponent</code> class is very simple, simpler even than <code>AppComponent</code>: it has no business logic, and its template has no links, just a title and <code>&lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code> for the crisis center child component.</p><a id="child-route-config"></a><h3 id="child-route-configuration" translation-result="on">子路由配置<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#child-route-configuration"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="child-route-configuration">Child route configuration<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#child-route-configuration"><i class="material-icons">link</i></a></h3><p translation-result="on">在 <code>crisis-center</code> 目录下生成一个 <code>CrisisCenterHome</code> 组件，作为 "危机中心" 特性的宿主页面。</p><p translation-origin="off">As a host page for the "Crisis Center" feature, generate a <code>CrisisCenterHome</code> component in the <code>crisis-center</code> folder.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component crisis-center/crisis-center-home</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">/</span><span class="pln">crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">-</span><span class="pln">home</span></code>
    </pre></aio-code></code-example><p translation-result="on">用一条欢迎信息修改 <code>Crisis Center</code> 中的模板。</p><p translation-origin="off">Update the template with a welcome message to the <code>Crisis Center</code>.</p><code-example path="router/src/app/crisis-center/crisis-center-home/crisis-center-home.component.html" header="src/app/crisis-center/crisis-center-home/crisis-center-home.component.html" ng-version="9.0.0-rc.11"><div style="display:none">&lt;p&gt;Welcome to the Crisis Center&lt;/p&gt;</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center-home/crisis-center-home.component.html</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center-home/crisis-center-home.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;p&gt;</span><span class="pln">Welcome to the Crisis Center</span><span class="tag">&lt;/p&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">把 <code>heroes-routing.module.ts</code> 文件复制过来，改名为 <code>crisis-center-routing.module.ts</code>，并修改它。 这次你要把<strong>子路由</strong>定义在父路由 <code>crisis-center</code> 中。</p><p translation-origin="off">Update the <code>crisis-center-routing.module.ts</code> you renamed after copying it from <code>heroes-routing.module.ts</code> file. This time, you define <strong>child routes</strong> <em>within</em> the parent <code>crisis-center</code> route.</p><code-example path="router/src/app/crisis-center/crisis-center-routing.module.1.ts" header="src/app/crisis-center/crisis-center-routing.module.ts (Routes)" region="routes" ng-version="9.0.0-rc.11"><div style="display:none">const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ];</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center-routing.module.ts (Routes)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center-routing.module.ts (Routes)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">const</span><span class="pln"> crisisCenterRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pun">,</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">':id'</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln">
          </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意，父路由 <code>crisis-center</code> 有一个 <code>children</code> 属性，它有一个包含 <code>CrisisListComponent</code> 的路由。 <code>CrisisListModule</code> 路由还有一个带两个路由的 <code>children</code> 数组。</p><p translation-origin="off">Notice that the parent <code>crisis-center</code> route has a <code>children</code> property with a single route containing the <code>CrisisListComponent</code>. The <code>CrisisListComponent</code> route also has a <code>children</code> array with two routes.</p><p translation-result="on">这两个路由导航到了<em>危机中心</em>的两个子组件：<code>CrisisCenterHomeComponent</code> 和 <code>CrisisDetailComponent</code>。</p><p translation-origin="off">These two routes navigate to the crisis center child components, <code>CrisisCenterHomeComponent</code> and <code>CrisisDetailComponent</code>, respectively.</p><p translation-result="on">对这些路由的处理中有一些<em>重要的不同</em>。</p><p translation-origin="off">There are <em>important differences</em> in the way the router treats these <em>child routes</em>.</p><p translation-result="on">路由器会把这些路由对应的组件放在 <code>CrisisCenterComponent</code> 的 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 中，而不是 <code>AppComponent</code> 壳组件中的。</p><p translation-origin="off">The router displays the components of these routes in the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> of the <code>CrisisCenterComponent</code>, not in the <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> of the <code>AppComponent</code> shell.</p><p translation-result="on"><code>CrisisListComponent</code> 包含危机列表和一个 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code>，用以显示 <code>Crisis Center Home</code> 和 <code>Crisis Detail</code> 这两个路由组件。</p><p translation-origin="off">The <code>CrisisListComponent</code> contains the crisis list and a <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> to display the <code>Crisis Center Home</code> and <code>Crisis Detail</code> route components.</p><p translation-result="on"><code>Crisis Detail</code> 路由是 <code>Crisis <a href="api/common/NumberSymbol#List" class="code-anchor">List</a></code> 的子路由。由于路由器默认会<a href="guide/router#reuse">复用组件</a>，因此当你选择了另一个危机时，<code>CrisisDetailComponent</code> 会被复用。<br>作为对比，回头看看 <code>Hero Detail</code> 路由，每当你从列表中选择了不同的英雄时，<a href="guide/router#snapshot-the-no-observable-alternative">都会重新创建该组件</a>。</p><p translation-origin="off">The <code>Crisis Detail</code> route is a child of the <code>Crisis <a href="api/common/NumberSymbol#List" class="code-anchor">List</a></code>. The router <a href="guide/router#reuse">reuses components</a> by default, so the <code>Crisis Detail</code> component will be re-used as you select different crises. In contrast, back in the <code>Hero Detail</code> route, <a href="guide/router#snapshot-the-no-observable-alternative">the component was recreated</a> each time you selected a different hero from the list of heroes.</p><p translation-result="on">在顶层，以 <code>/</code> 开头的路径指向的总是应用的根。 但这里是子路由。 它们是在父路由路径的基础上做出的扩展。 在路由树中每深入一步，你就会在该路由的路径上添加一个斜线 <code>/</code>（除非该路由的路径是<em>空的</em>）。</p><p translation-origin="off">At the top level, paths that begin with <code>/</code> refer to the root of the application. But child routes <em>extend</em> the path of the parent route. With each step down the route tree, you add a slash followed by the route path, unless the path is <em>empty</em>.</p><p translation-result="on">如果把该逻辑应用到危机中心中的导航，那么父路径就是 <code>/crisis-center</code>。</p><p translation-origin="off">Apply that logic to navigation within the crisis center for which the parent path is <code>/crisis-center</code>.</p><ul><li><p translation-result="on">要导航到 <code>CrisisCenterHomeComponent</code>，完整的 URL 是 <code>/crisis-center</code> (<code>/crisis-center</code> + <code>''</code> + <code>''</code>)。</p><p translation-origin="off">To navigate to the <code>CrisisCenterHomeComponent</code>, the full URL is <code>/crisis-center</code> (<code>/crisis-center</code> + <code>''</code> + <code>''</code>).</p></li><li><p translation-result="on">要导航到 <code>CrisisDetailComponent</code> 以展示 <code>id=2</code> 的危机，完整的 URL 是 <code>/crisis-center/2</code> (<code>/crisis-center</code> + <code>''</code> + <code>'/2'</code>)。</p><p translation-origin="off">To navigate to the <code>CrisisDetailComponent</code> for a crisis with <code>id=2</code>, the full URL is <code>/crisis-center/2</code> (<code>/crisis-center</code> + <code>''</code> + <code>'/2'</code>).</p></li></ul><p translation-result="on">本例子中包含站点部分的绝对 URL，就是：</p><p translation-origin="off">The absolute URL for the latter example, including the <code>localhost</code> origin, is</p><code-example ng-version="9.0.0-rc.11"><div style="display:none">localhost:4200/crisis-center/2</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">4200</span><span class="pun">/</span><span class="pln">crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">/</span><span class="lit">2</span></code>
    </pre></aio-code></code-example><p translation-result="on">这里是完整的 <code>crisis-center.routing.ts</code> 及其导入语句。</p><p translation-origin="off">Here's the complete <code>crisis-center-routing.module.ts</code> file with its imports.</p><code-example path="router/src/app/crisis-center/crisis-center-routing.module.1.ts" header="src/app/crisis-center/crisis-center-routing.module.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(crisisCenterRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class CrisisCenterRoutingModule { }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center-routing.module.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center-routing.module.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center-home/crisis-center-home.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-center.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-detail/crisis-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> crisisCenterRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pun">,</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">':id'</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln">
          </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">crisisCenterRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisCenterRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><a id="import-crisis-module"></a><h3 id="import-crisis-center-module-into-the-appmodule-routes" translation-result="on">把危机中心模块导入到 <code>AppModule</code> 的路由中<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#import-crisis-center-module-into-the-appmodule-routes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="import-crisis-center-module-into-the-appmodule-routes">Import crisis center module into the <em>AppModule</em> routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#import-crisis-center-module-into-the-appmodule-routes"><i class="material-icons">link</i></a></h3><p translation-result="on">就像 <code>HeroesModule</code> 模块中一样，你必须把 <code>CrisisCenterModule</code> 添加到 <code>AppModule</code> 的 <code>imports</code> 数组中，就在 <code>AppRoutingModule</code> 前面：</p><p translation-origin="off">As with the <code>HeroesModule</code>, you must add the <code>CrisisCenterModule</code> to the <code>imports</code> array of the <code>AppModule</code> <em>before</em> the <code>AppRoutingModule</code>:</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane path="router/src/app/crisis-center/crisis-center.module.ts" header="src/app/crisis-center/crisis-center.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CrisisCenterRoutingModule } from './crisis-center-routing.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, CrisisCenterRoutingModule ], declarations: [ CrisisCenterComponent, CrisisListComponent, CrisisCenterHomeComponent, CrisisDetailComponent ] }) export class CrisisCenterModule {}</code-pane><code-pane path="router/src/app/app.module.4.ts" header="src/app/app.module.ts (import CrisisCenterModule)" region="crisis-center-module">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { CrisisCenterModule } from './crisis-center/crisis-center.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, CrisisCenterModule, AppRoutingModule ], declarations: [ AppComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-3-0" tabindex="0" aria-posinset="1" aria-setsize="2" aria-controls="mat-tab-content-3-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/crisis-center/crisis-center.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-3-1" tabindex="-1" aria-posinset="2" aria-setsize="2" aria-controls="mat-tab-content-3-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/app.module.ts (import CrisisCenterModule)</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:316px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-24 mat-tab-body-active ng-star-inserted" id="mat-tab-content-3-0" aria-labelledby="mat-tab-label-3-0"><div class="mat-tab-body-content ng-tns-c50-24 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/common'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center-home/crisis-center-home.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-center.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-detail/crisis-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center-routing.module'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisCenterRoutingModule</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">CrisisCenterComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisCenterHomeComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisDetailComponent</span><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisCenterModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-25 ng-star-inserted" id="mat-tab-content-3-1" aria-labelledby="mat-tab-label-3-1"><div class="mat-tab-body-content ng-tns-c50-25 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><p translation-result="on">从 <code>app.routing.ts</code> 中移除危机中心的初始路由。 这些特性路由现在是由 <code>HeroesModule</code> 和 <code>CrisisCenter</code> 特性模块提供的。</p><p translation-origin="off">Remove the initial crisis center route from the <code>app-routing.module.ts</code>. The feature routes are now provided by the <code>HeroesModule</code> and the <code>CrisisCenter</code> modules.</p><p translation-result="on"><code>app-routing.module.ts</code> 文件中只有应用的顶层路由，比如默认路由和通配符路由。</p><p translation-origin="off">The <code>app-routing.module.ts</code> file retains the top-level application routes such as the default and wildcard routes.</p><code-example path="router/src/app/app-routing.module.3.ts" header="src/app/app-routing.module.ts (v3)" region="v3" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true } // &lt;-- debugging purposes only ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule {}</div><header class="ng-star-inserted">src/app/app-routing.module.ts (v3)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (v3)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">                </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">   </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/heroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><a id="relative-navigation"></a><h3 id="relative-navigation" translation-result="on">相对导航<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#relative-navigation"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="relative-navigation">Relative navigation<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#relative-navigation"><i class="material-icons">link</i></a></h3><p translation-result="on">虽然构建出了危机中心特性区，你却仍在使用以斜杠开头的<strong>绝对路径</strong>来导航到危机详情的路由。</p><p translation-origin="off">While building out the crisis center feature, you navigated to the crisis detail route using an <strong>absolute path</strong> that begins with a <em>slash</em>.</p><p translation-result="on">路由器会从路由配置的顶层来匹配像这样的<em>绝对路径</em>。</p><p translation-origin="off">The router matches such <em>absolute</em> paths to routes starting from the top of the route configuration.</p><p translation-result="on">你固然可以继续像<em>危机中心</em>特性区一样使用绝对路径，但是那样会把链接钉死在特定的父路由结构上。 如果你修改了父路径 <code>/crisis-center</code>，那就不得不修改每一个链接参数数组。</p><p translation-origin="off">You could continue to use absolute paths like this to navigate inside the <em>Crisis Center</em> feature, but that pins the links to the parent routing structure. If you changed the parent <code>/crisis-center</code> path, you would have to change the link parameters array.</p><p translation-result="on">通过改成定义<em>相对于</em>当前 URL 的路径，你可以把链接从这种依赖中解放出来。 当你修改了该特性区的父路由路径时，该特性区<em>内部</em>的导航仍然完好无损。</p><p translation-origin="off">You can free the links from this dependency by defining paths that are <strong>relative</strong> to the current URL segment. Navigation <em>within</em> the feature area remains intact even if you change the parent route path to the feature.</p><p translation-result="on">例子如下：</p><p translation-origin="off">Here's an example:</p><div class="alert is-helpful"><p translation-result="on">路由器支持在<em>链接参数数组</em>中使用“目录式”语法来为查询路由名提供帮助：</p><p translation-origin="off">The router supports directory-like syntax in a <em>link parameters list</em> to help guide route name lookup:</p><p translation-result="on"><code>./</code> 或 <code>无前导斜线</code> 形式是相对于当前级别的。</p><p translation-origin="off"><code>./</code> or <code>no leading slash</code> is relative to the current level.</p><p translation-result="on"><code>../</code> 会回到当前路由路径的上一级。</p><p translation-origin="off"><code>../</code> to go up one level in the route path.</p><p translation-result="on">你可以把相对导航语法和一个祖先路径组合起来用。 如果不得不导航到一个兄弟路由，你可以用 <code>../&lt;sibling&gt;</code> 来回到上一级，然后进入兄弟路由路径中。</p><p translation-origin="off">You can combine relative navigation syntax with an ancestor path. If you must navigate to a sibling route, you could use the <code>../&lt;sibling&gt;</code> convention to go up one level, then over and down the sibling route path.</p></div><p translation-result="on">用 <code>Router.navigate</code> 方法导航到相对路径时，你必须提供当前的 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>，来让路由器知道你现在位于路由树中的什么位置。</p><p translation-origin="off">To navigate a relative path with the <code>Router.navigate</code> method, you must supply the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> to give the router knowledge of where you are in the current route tree.</p><p translation-result="on">在<em>链接参数数组</em>后面，添加一个带有 <code><a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a></code> 属性的对象，并把它设置为当前的 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>。 这样路由器就会基于当前激活路由的位置来计算出目标 URL。</p><p translation-origin="off">After the <em>link parameters array</em>, add an object with a <code><a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a></code> property set to the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>. The router then calculates the target URL based on the active route's location.</p><div class="alert is-helpful"><p translation-result="on">当调用路由器的 <code>navigateByUrl</code> 时，<strong>总是</strong>要指定完整的<em>绝对路径</em>。</p><p translation-origin="off"><strong>Always</strong> specify the complete <em>absolute</em> path when calling router's <code>navigateByUrl</code> method.</p></div><a id="nav-to-crisis"></a><h3 id="navigate-to-crisis-list-with-a-relative-url" translation-result="on">使用相对 URL 导航到危机列表<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#navigate-to-crisis-list-with-a-relative-url"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="navigate-to-crisis-list-with-a-relative-url">Navigate to crisis list with a relative URL<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#navigate-to-crisis-list-with-a-relative-url"><i class="material-icons">link</i></a></h3><p translation-result="on">你已经注入过了 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>，你需要把它来和相对导航路径组合在一起。</p><p translation-origin="off">You've already injected the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> that you need to compose the relative navigation path.</p><p translation-result="on">如果用 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 来代替 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务进行导航，就要使用<em>相同</em>的链接参数数组，不过不再需要提供 <code><a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a></code> 属性。 <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 已经隐含在了 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令中。</p><p translation-origin="off">When using a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> to navigate instead of the <code><a href="api/router/Router" class="code-anchor">Router</a></code> service, you'd use the <em>same</em> link parameters array, but you wouldn't provide the object with the <code><a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a></code> property. The <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> is implicit in a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directive.</p><p translation-result="on">修改 <code>CrisisDetailComponent</code> 的 <code>gotoCrises</code> 方法，来使用相对路径返回<em>危机中心</em>列表。</p><p translation-origin="off">Update the <code>gotoCrises</code> method of the <code>CrisisDetailComponent</code> to navigate back to the <em>Crisis Center</em> list using relative path navigation.</p><code-example path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts" header="src/app/crisis-center/crisis-detail/crisis-detail.component.ts (relative navigation)" region="gotoCrises-navigate" ng-version="9.0.0-rc.11"><div style="display:none">// Relative navigation back to the crises this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { <a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a>: this.route });</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail/crisis-detail.component.ts (relative navigation)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail/crisis-detail.component.ts (relative navigation)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="com">// Relative navigation back to the crises</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'../'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> crisisId</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">:</span><span class="pln"> </span><span class="str">'foo'</span><span class="pln"> </span><span class="pun">}],</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/NavigationExtras#relativeTo" class="code-anchor"><span class="pln">relativeTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route </span><span class="pun">});</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意这个路径使用了 <code>../</code> 语法返回上一级。 如果当前危机的 <code>id</code> 是 <code>3</code>，那么最终返回到的路径就是 <code>/crisis-center/;id=3;foo=foo</code>。</p><p translation-origin="off">Notice that the path goes up a level using the <code>../</code> syntax. If the current crisis <code>id</code> is <code>3</code>, the resulting path back to the crisis list is <code>/crisis-center/;id=3;foo=foo</code>.</p><a id="named-outlets"></a><h3 id="displaying-multiple-routes-in-named-outlets" translation-result="on">用命名出口（outlet）显示多重路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#displaying-multiple-routes-in-named-outlets"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="displaying-multiple-routes-in-named-outlets">Displaying multiple routes in named outlets<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#displaying-multiple-routes-in-named-outlets"><i class="material-icons">link</i></a></h3><p translation-result="on">你决定给用户提供一种方式来联系危机中心。 当用户点击“Contact”按钮时，你要在一个弹出框中显示一条消息。</p><p translation-origin="off">You decide to give users a way to contact the crisis center. When a user clicks a "Contact" button, you want to display a message in a popup view.</p><p translation-result="on">即使在应用中的不同页面之间切换，这个弹出框也应该始终保持打开状态，直到用户发送了消息或者手动取消。 显然，你不能把这个弹出框跟其它放到页面放到同一个路由出口中。</p><p translation-origin="off">The popup should stay open, even when switching between pages in the application, until the user closes it by sending the message or canceling. Clearly you can't put the popup in the same outlet as the other pages.</p><p translation-result="on">迄今为止，你只定义过单路由出口，并且在其中嵌套了子路由以便对路由分组。 在每个模板中，路由器只能支持一个<em>无名</em>主路由出口。</p><p translation-origin="off">Until now, you've defined a single outlet and you've nested child routes under that outlet to group routes together. The router only supports one primary <em>unnamed</em> outlet per template.</p><p translation-result="on">模板还可以有多个<em>命名的</em>路由出口。 每个命名出口都自己有一组带组件的路由。 多重出口可以在同一时间根据不同的路由来显示不同的内容。</p><p translation-origin="off">A template can also have any number of <em>named</em> outlets. Each named outlet has its own set of routes with their own components. Multiple outlets can be displaying different content, determined by different routes, all at the same time.</p><p translation-result="on">在 <code>AppComponent</code> 中添加一个名叫“popup”的出口，就在无名出口的下方。</p><p translation-origin="off">Add an outlet named "popup" in the <code>AppComponent</code>, directly below the unnamed outlet.</p><code-example path="router/src/app/app.component.4.html" header="src/app/app.component.html (outlets)" region="outlets" ng-version="9.0.0-rc.11"><div style="display:none">&lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> name="popup"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/app.component.html (outlets)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html (outlets)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;div</span><span class="pln"> [@</span><span class="atn">routeAnimation</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"getAnimationData(routerOutlet)"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> #</span><span class="atn">routerOutlet</span><span class="pun">=</span><span class="atv">"outlet"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"popup"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">一旦你学会了如何把一个弹出框组件路由到该出口，那里就是将会出现弹出框的地方。</p><p translation-origin="off">That's where a popup will go, once you learn how to route a popup component to it.</p><a id="secondary-routes"></a><h4 id="secondary-routes" translation-result="on">第二路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#secondary-routes"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="secondary-routes">Secondary routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#secondary-routes"><i class="material-icons">link</i></a></h4><p translation-result="on">命名出口是<em>第二路由</em>的目标。</p><p translation-origin="off">Named outlets are the targets of <em>secondary routes</em>.</p><p translation-result="on">第二路由很像主路由，配置方式也一样。它们只有一些关键的不同点：</p><p translation-origin="off">Secondary routes look like primary routes and you configure them the same way. They differ in a few key respects.</p><ul><li><p translation-result="on">它们彼此互不依赖。</p><p translation-origin="off">They are independent of each other.</p></li><li><p translation-result="on">它们与其它路由组合使用。</p><p translation-origin="off">They work in combination with other routes.</p></li><li><p translation-result="on">它们显示在命名出口中。</p><p translation-origin="off">They are displayed in named outlets.</p></li></ul><p translation-result="on">生成一个新的组件来组合这个消息。</p><p translation-origin="off">Generate a new component to compose the message.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component compose-message</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component compose</span><span class="pun">-</span><span class="pln">message</span></code>
    </pre></aio-code></code-example><p translation-result="on">它显示一个简单的表单，包括一个头、一个消息输入框和两个按钮：“Send”和“Cancel”。</p><p translation-origin="off">It displays a simple form with a header, an input box for the message, and two buttons, "Send" and "Cancel".</p><div class="lightbox"><img src="generated/images/guide/router/contact-popup.png" alt="Contact popup" width="250" height="262"></div><p translation-result="on">下面是该组件及其模板和样式：</p><p translation-origin="off">Here's the component, its template and styles:</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="src/app/compose-message/compose-message.component.css" path="router/src/app/compose-message/compose-message.component.css">:<a href="api/core/Directive#host" class="code-anchor">host</a> { <a href="api/router/Scroll#position" class="code-anchor">position</a>: relative; bottom: 10%; }</code-pane><code-pane header="src/app/compose-message/compose-message.component.html" path="router/src/app/compose-message/compose-message.component.html">&lt;h3&gt;Contact Crisis Center&lt;/h3&gt; &lt;div *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="details"&gt; {{ details }} &lt;/div&gt; &lt;div&gt; &lt;div&gt; &lt;label&gt;Message: &lt;/label&gt; &lt;/div&gt; &lt;div&gt; &lt;<a href="api/forms/DefaultValueAccessor" class="code-anchor">textarea</a> [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>" rows="10" cols="35" [disabled]="sending"&gt;&lt;/<a href="api/forms/DefaultValueAccessor" class="code-anchor">textarea</a>&gt; &lt;/div&gt; &lt;/div&gt; &lt;p *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="!sending"&gt; &lt;button (click)="send()"&gt;Send&lt;/button&gt; &lt;button (click)="cancel()"&gt;Cancel&lt;/button&gt; &lt;/p&gt;</code-pane><code-pane header="src/app/compose-message/compose-message.component.ts" path="router/src/app/compose-message/compose-message.component.ts">import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/HostBinding" class="code-anchor">HostBinding</a> } from '@angular/core'; import { <a href="api/router/Router" class="code-anchor">Router</a> } from '@angular/router'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-compose-message', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './compose-message.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./compose-message.component.css'] }) export class ComposeMessageComponent { details: string; <a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>: string; sending = false; constructor(private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} send() { this.sending = true; this.details = 'Sending Message...'; setTimeout(() =&gt; { this.sending = false; this.closePopup(); }, 1000); } cancel() { this.closePopup(); } closePopup() { // Providing a `null` value to the named outlet // clears the contents of the named outlet this.router.navigate([{ outlets: { popup: null }}]); } }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-4-0" tabindex="0" aria-posinset="1" aria-setsize="3" aria-controls="mat-tab-content-4-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/compose-message/compose-message.component.css</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-4-1" tabindex="-1" aria-posinset="2" aria-setsize="3" aria-controls="mat-tab-content-4-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/compose-message/compose-message.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-4-2" tabindex="-1" aria-posinset="3" aria-setsize="3" aria-controls="mat-tab-content-4-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/compose-message/compose-message.component.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:436px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-26 mat-tab-body-active ng-star-inserted" id="mat-tab-content-4-0" aria-labelledby="mat-tab-label-4-0"><div class="mat-tab-body-content ng-tns-c50-26 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/compose-message/compose-message.component.css">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">:</span><a href="api/core/Directive#host" class="code-anchor"><span class="pln">host</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/Scroll#position" class="code-anchor"><span class="pln">position</span></a><span class="pun">:</span><span class="pln"> relative</span><span class="pun">;</span><span class="pln"> bottom</span><span class="pun">:</span><span class="pln"> </span><span class="lit">10</span><span class="pun">%;</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-27 ng-star-inserted" id="mat-tab-content-4-1" aria-labelledby="mat-tab-label-4-1"><div class="mat-tab-body-content ng-tns-c50-27 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-28 ng-star-inserted" id="mat-tab-content-4-2" aria-labelledby="mat-tab-label-4-2"><div class="mat-tab-body-content ng-tns-c50-28 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><p translation-result="on">它看起来几乎和你以前见过其它组件一样，但有两个值得注意的区别。</p><p translation-origin="off">It looks about the same as any other component you've seen in this guide. There are two noteworthy differences.</p><p translation-result="on">注意，<code>send()</code> 方法在发送消息和关闭弹出框之前通过等待模拟了一秒钟的延迟。</p><p translation-origin="off">Note that the <code>send()</code> method simulates latency by waiting a second before "sending" the message and closing the popup.</p><p translation-result="on"><code>closePopup()</code> 方法用把 <code>popup</code> 出口导航到 <code>null</code> 的方式关闭了弹出框。 这个奇怪的用法在<a href="guide/router#clear-secondary-routes">稍后的部分</a>有讲解。</p><p translation-origin="off">The <code>closePopup()</code> method closes the popup view by navigating to the popup outlet with a <code>null</code>. That's a peculiarity covered <a href="guide/router#clear-secondary-routes">below</a>.</p><a id="add-secondary-route"></a><h4 id="add-a-secondary-route" translation-result="on">添加第二路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-a-secondary-route"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="add-a-secondary-route">Add a secondary route<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-a-secondary-route"><i class="material-icons">link</i></a></h4><p translation-result="on">打开 <code>AppRoutingModule</code>，并把一个新的 <code>compose</code> 路由添加到 <code>appRoutes</code> 中。</p><p translation-origin="off">Open the <code>AppRoutingModule</code> and add a new <code>compose</code> route to the <code>appRoutes</code>.</p><code-example path="router/src/app/app-routing.module.3.ts" header="src/app/app-routing.module.ts (compose route)" region="compose" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'compose', component: ComposeMessageComponent, outlet: 'popup' },</div><header class="ng-star-inserted">src/app/app-routing.module.ts (compose route)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (compose route)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln">
  path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'compose'</span><span class="pun">,</span><span class="pln">
  component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pun">,</span><span class="pln">
  outlet</span><span class="pun">:</span><span class="pln"> </span><span class="str">'popup'</span><span class="pln">
</span><span class="pun">},</span></code>
    </pre></aio-code></code-example><p translation-result="on">对 <code>path</code> 和 <code>component</code> 属性应该很熟悉了吧。 注意这个新的属性 <code>outlet</code> 被设置成了 <code>'popup'</code>。 这个路由现在指向了 <code>popup</code> 出口，而 <code>ComposeMessageComponent</code> 也将显示在那里。</p><p translation-origin="off">The <code>path</code> and <code>component</code> properties should be familiar. There's a new property, <code>outlet</code>, set to <code>'popup'</code>. This route now targets the popup outlet and the <code>ComposeMessageComponent</code> will display there.</p><p translation-result="on">用户需要某种途径来打开这个弹出框。 打开 <code>AppComponent</code>，并添加一个“Contact”链接。</p><p translation-origin="off">The user needs a way to open the popup. Open the <code>AppComponent</code> and add a "Contact" link.</p><code-example path="router/src/app/app.component.4.html" header="src/app/app.component.html (contact-link)" region="contact-link" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt;</div><header class="ng-star-inserted">src/app/app.component.html (contact-link)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html (contact-link)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"[{ outlets: { popup: ['compose'] } }]"</span><span class="tag">&gt;</span><span class="pln">Contact</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">虽然 <code>compose</code> 路由被钉死在了 <code>popup</code> 出口上，但这仍然不足以向 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令表明要加载该路由。 你还要在<em>链接参数数组</em>中指定这个命名出口，并通过属性绑定的形式把它绑定到 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 上。</p><p translation-origin="off">Although the <code>compose</code> route is pinned to the "popup" outlet, that's not sufficient for wiring the route to a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directive. You have to specify the named outlet in a <em>link parameters array</em> and bind it to the <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> with a property binding.</p><p translation-result="on"><em>链接参数数组</em>包含一个只有一个 <code>outlets</code> 属性的对象，它的值是另一个对象，这个对象以一个或多个路由的出口名作为属性名。 在这里，它只有一个出口名“popup”，它的值则是另一个<em>链接参数数组</em>，用于指定 <code>compose</code> 路由。</p><p translation-origin="off">The <em>link parameters array</em> contains an object with a single <code>outlets</code> property whose value is another object keyed by one (or more) outlet names. In this case there is only the "popup" outlet property and its value is another <em>link parameters array</em> that specifies the <code>compose</code> route.</p><p translation-result="on">意思是，当用户点击此链接时，在路由出口 <code>popup</code> 中显示与 <code>compose</code> 路由相关联的组件。</p><p translation-origin="off">You are in effect saying, <em>when the user clicks this link, display the component associated with the <code>compose</code> route in the <code>popup</code> outlet</em>.</p><div class="alert is-helpful"><p translation-result="on">当只需要考虑一个路由和一个<em>无名</em>出口时，外部对象中的这个 <code>outlets</code> 对象是完全不必要的。</p><p translation-origin="off">This <code>outlets</code> object within an outer object was completely unnecessary when there was only one route and one <em>unnamed</em> outlet to think about.</p><p translation-result="on">路由器假设这个路由指向了<em>无名</em>的主出口，并为你创建这些对象。</p><p translation-origin="off">The router assumed that your route specification targeted the <em>unnamed</em> primary outlet and created these objects for you.</p><p translation-result="on">路由到一个命名出口就会揭示一个以前被隐藏的真相： 你可以在同一个 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令中为多个路由出口指定多个路由。</p><p translation-origin="off">Routing to a named outlet has revealed a previously hidden router truth: you can target multiple outlets with multiple routes in the same <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directive.</p><p translation-result="on">这里你实际上没能这样做。要想指向命名出口，你就得使用一种更强大也更啰嗦的语法。</p><p translation-origin="off">You're not actually doing that here. But to target a named outlet, you must use the richer, more verbose syntax.</p></div><a id="secondary-route-navigation"></a><h4 id="secondary-route-navigation-merging-routes-during-navigation" translation-result="on">第二路由导航：在导航期间合并路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#secondary-route-navigation-merging-routes-during-navigation"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="secondary-route-navigation-merging-routes-during-navigation">Secondary route navigation: merging routes during navigation<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#secondary-route-navigation-merging-routes-during-navigation"><i class="material-icons">link</i></a></h4><p translation-result="on">导航到<em>危机中心</em>并点击“Contact”，你将会在浏览器的地址栏看到如下 URL：</p><p translation-origin="off">Navigate to the <em>Crisis Center</em> and click "Contact". you should see something like the following URL in the browser address bar.</p><code-example ng-version="9.0.0-rc.11"><div style="display:none">http://.../crisis-center(popup:compose)</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">http</span><span class="pun">:</span><span class="com">//.../crisis-center(popup:compose)</span></code>
    </pre></aio-code></code-example><p translation-result="on">这个 URL 中有意思的部分是 <code>...</code> 后面的这些：</p><p translation-origin="off">The interesting part of the URL follows the <code>...</code>:</p><ul><li><p translation-result="on"> <code>crisis-center</code> 是主导航。</p><p translation-origin="off">The <code>crisis-center</code> is the primary navigation.</p></li><li><p translation-result="on">圆括号包裹的部分是第二路由。</p><p translation-origin="off">Parentheses surround the secondary route.</p></li><li><p translation-result="on">第二路由包括一个出口名称（<code>popup</code>）、一个冒号分隔符和第二路由的路径（<code>compose</code>）。</p><p translation-origin="off">The secondary route consists of an outlet name (<code>popup</code>), a <code>colon</code> separator, and the secondary route path (<code>compose</code>).</p></li></ul><p translation-result="on">点击 <em>Heroes</em> 链接，并再次查看 URL：</p><p translation-origin="off">Click the <em>Heroes</em> link and look at the URL again.</p><code-example ng-version="9.0.0-rc.11"><div style="display:none">http://.../heroes(popup:compose)</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">http</span><span class="pun">:</span><span class="com">//.../heroes(popup:compose)</span></code>
    </pre></aio-code></code-example><p translation-result="on">主导航的部分变化了，而第二路由没有变。</p><p translation-origin="off">The primary navigation part has changed; the secondary route is the same.</p><p translation-result="on">路由器在导航树中对两个独立的分支保持追踪，并在 URL 中对这棵树进行表达。</p><p translation-origin="off">The router is keeping track of two separate branches in a navigation tree and generating a representation of that tree in the URL.</p><p translation-result="on">你还可以添加更多出口和更多路由（无论是在顶层还是在嵌套的子层）来创建一个带有多个分支的导航树。 路由器将会生成相应的 URL。</p><p translation-origin="off">You can add many more outlets and routes, at the top level and in nested levels, creating a navigation tree with many branches. The router will generate the URL to go with it.</p><p translation-result="on">通过像前面那样填充 <code>outlets</code> 对象，你可以告诉路由器立即导航到一棵完整的树。 然后把这个对象通过一个<em>链接参数数组</em>传给 <code>router.navigate</code> 方法。</p><p translation-origin="off">You can tell the router to navigate an entire tree at once by filling out the <code>outlets</code> object mentioned above. Then pass that object inside a <em>link parameters array</em> to the <code>router.navigate</code> method.</p><p translation-result="on">有空的时候你可以自行试验这些可能性。</p><p translation-origin="off">Experiment with these possibilities at your leisure.</p><a id="clear-secondary-routes"></a><h4 id="clearing-secondary-routes" translation-result="on">清除第二路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#clearing-secondary-routes"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="clearing-secondary-routes">Clearing secondary routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#clearing-secondary-routes"><i class="material-icons">link</i></a></h4><p translation-result="on">正如你刚刚学到的，除非导航到新的组件，否则路由出口中的组件会始终存在。 这里涉及到的第二出口也同样如此。</p><p translation-origin="off">As you've learned, a component in an outlet persists until you navigate away to a new component. Secondary outlets are no different in this regard.</p><p translation-result="on">每个第二出口都有自己独立的导航，跟主出口的导航彼此独立。 修改主出口中的当前路由并不会影响到 <code>popup</code> 出口中的。 这就是为什么在危机中心和英雄管理之间导航时，弹出框始终都是可见的。</p><p translation-origin="off">Each secondary outlet has its own navigation, independent of the navigation driving the primary outlet. Changing a current route that displays in the primary outlet has no effect on the popup outlet. That's why the popup stays visible as you navigate among the crises and heroes.</p><p translation-result="on">点击“send”或“cancel”按钮，则<em>会</em>清除弹出框视图。 为何如此？再看看 <code>closePopup()</code> 方法：</p><p translation-origin="off">Clicking the "send" or "cancel" buttons <em>does</em> clear the popup view. To see how, look at the <code>closePopup()</code> method again:</p><code-example path="router/src/app/compose-message/compose-message.component.ts" header="src/app/compose-message/compose-message.component.ts (closePopup)" region="closePopup" ng-version="9.0.0-rc.11"><div style="display:none">closePopup() { // Providing a `null` value to the named outlet // clears the contents of the named outlet this.router.navigate([{ outlets: { popup: null }}]); }</div><header class="ng-star-inserted">src/app/compose-message/compose-message.component.ts (closePopup)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/compose-message/compose-message.component.ts (closePopup)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">closePopup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// Providing a `null` value to the named outlet</span><span class="pln">
  </span><span class="com">// clears the contents of the named outlet</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([{</span><span class="pln"> outlets</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> popup</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">}}]);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">它使用 <code><a href="api/router/Router#navigate" class="code-anchor">Router.navigate()</a></code> 方法进行强制导航，并传入了一个<a href="guide/router#link-parameters-array">链接参数数组</a>。</p><p translation-origin="off">It navigates imperatively with the <code><a href="api/router/Router#navigate" class="code-anchor">Router.navigate()</a></code> method, passing in a <a href="guide/router#link-parameters-array">link parameters array</a>.</p><p translation-result="on">就像在 <code>AppComponent</code> 中绑定到的 <em>Contact</em> <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 一样，它也包含了一个带 <code>outlets</code> 属性的对象。 <code>outlets</code> 属性的值是另一个对象，该对象用一些出口名称作为属性名。 唯一的命名出口是 <code>'popup'</code>。</p><p translation-origin="off">Like the array bound to the <em>Contact</em> <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> in the <code>AppComponent</code>, this one includes an object with an <code>outlets</code> property. The <code>outlets</code> property value is another object with outlet names for keys. The only named outlet is <code>'popup'</code>.</p><p translation-result="on">但这次，<code>'popup'</code> 的值是 <code>null</code>。<code>null</code> 不是一个路由，但却是一个合法的值。 把 <code>popup</code> 这个 <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> 设置为 <code>null</code> 会清除该出口，并且从当前 URL 中移除第二路由 <code>popup</code>。</p><p translation-origin="off">This time, the value of <code>'popup'</code> is <code>null</code>. That's not a route, but it is a legitimate value. Setting the popup <code><a href="api/router/RouterOutlet" class="code-anchor">RouterOutlet</a></code> to <code>null</code> clears the outlet and removes the secondary popup route from the current URL.</p><a id="guards"></a><h2 id="milestone-5-route-guards" translation-result="on">里程碑 5：路由守卫<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-5-route-guards"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-5-route-guards">Milestone 5: Route guards<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-5-route-guards"><i class="material-icons">link</i></a></h2><p translation-result="on">现在，<em>任何用户</em>都能在<em>任何时候</em>导航到<em>任何地方</em>。 但有时候这样是不对的。</p><p translation-origin="off">At the moment, <em>any</em> user can navigate <em>anywhere</em> in the application <em>anytime</em>. That's not always the right thing to do.</p><ul><li><p translation-result="on">该用户可能无权导航到目标组件。</p><p translation-origin="off">Perhaps the user is not authorized to navigate to the target component.</p></li><li><p translation-result="on">可能用户得先登录（认证）。</p><p translation-origin="off">Maybe the user must login (<em>authenticate</em>) first.</p></li><li><p translation-result="on">在显示目标组件前，你可能得先获取某些数据。</p><p translation-origin="off">Maybe you should fetch some data before you display the target component.</p></li><li><p translation-result="on">在离开组件前，你可能要先保存修改。</p><p translation-origin="off">You might want to save pending changes before leaving a component.</p></li><li><p translation-result="on">你可能要询问用户：你是否要放弃本次更改，而不用保存它们？</p><p translation-origin="off">You might ask the user if it's OK to discard pending changes rather than save them.</p></li></ul><p translation-result="on">你可以往路由配置中添加<strong><em>守卫</em></strong>，来处理这些场景。</p><p translation-origin="off">You add <em>guards</em> to the route configuration to handle these scenarios.</p><p translation-result="on">守卫返回一个值，以控制路由器的行为：</p><p translation-origin="off">A guard's return value controls the router's behavior:</p><ul><li><p translation-result="on">如果它返回 <code>true</code>，导航过程会继续</p><p translation-origin="off">If it returns <code>true</code>, the navigation process continues.</p></li><li><p translation-result="on">如果它返回 <code>false</code>，导航过程就会终止，且用户留在原地。</p><p translation-origin="off">If it returns <code>false</code>, the navigation process stops and the user stays put.</p></li><li><p translation-result="on">如果它返回 <code><a href="api/router/UrlTree" class="code-anchor">UrlTree</a></code>，则取消当前的导航，并且开始导航到返回的这个 <code><a href="api/router/UrlTree" class="code-anchor">UrlTree</a></code>.</p><p translation-origin="off">If it returns a <code><a href="api/router/UrlTree" class="code-anchor">UrlTree</a></code>, the current navigation cancels and a new navigation is initiated to the <code><a href="api/router/UrlTree" class="code-anchor">UrlTree</a></code> returned.</p></li></ul><div class="alert is-helpful"><p translation-result="on"><strong>注意</strong>：守卫还可以告诉路由器导航到别处，这样也会取消当前的导航。要想在守卫中这么做，就要返回 <code>false</code>；</p><p translation-origin="off"><strong>Note:</strong> The guard can also tell the router to navigate elsewhere, effectively canceling the current navigation. When doing so inside a guard, the guard should return <code>false</code>;</p></div><p translation-result="on">守卫<em>可以</em>用同步的方式返回一个布尔值。但在很多情况下，守卫无法用同步的方式给出答案。 守卫可能会向用户问一个问题、把更改保存到服务器，或者获取新数据，而这些都是异步操作。</p><p translation-origin="off">The guard <em>might</em> return its boolean answer synchronously. But in many cases, the guard can't produce an answer synchronously. The guard could ask the user a question, save changes to the server, or fetch fresh data. These are all asynchronous operations.</p><p translation-result="on">因此，路由的守卫可以返回一个 <code>Observable&lt;boolean&gt;</code> 或 <code>Promise&lt;boolean&gt;</code>，并且路由器会等待这个可观察对象被解析为 <code>true</code> 或 <code>false</code>。</p><p translation-origin="off">Accordingly, a routing guard can return an <code>Observable&lt;boolean&gt;</code> or a <code>Promise&lt;boolean&gt;</code> and the router will wait for the observable to resolve to <code>true</code> or <code>false</code>.</p><div class="alert is-critical"><p translation-result="on"><strong>注意：</strong> 提供给路由器的可观察对象还<em>必须</em>能结束（complete）。否则，导航就不会继续。</p><p translation-origin="off"><strong>Note:</strong> The observable provided to the Router <em>must</em> also complete. If the observable does not complete, the navigation will not continue.</p></div><p translation-result="on">路由器可以支持多种守卫接口：</p><p translation-origin="off">The router supports multiple guard interfaces:</p><ul><li><p translation-result="on">用<a href="api/router/CanActivate"><code>CanActivate</code></a>来处理导航<em>到</em>某路由的情况。</p><p translation-origin="off"><a href="api/router/CanActivate"><code>CanActivate</code></a>to mediate navigation <em>to</em> a route.</p></li><li><p translation-result="on">用<a href="api/router/CanActivateChild"><code>CanActivateChild</code></a>来处理导航<em>到</em>某子路由的情况。</p><p translation-origin="off"><a href="api/router/CanActivateChild"><code>CanActivateChild</code></a>to mediate navigation <em>to</em> a child route.</p></li><li><p translation-result="on">用<a href="api/router/CanDeactivate"><code>CanDeactivate</code></a>来处理从当前路由<em>离开</em>的情况.</p><p translation-origin="off"><a href="api/router/CanDeactivate"><code>CanDeactivate</code></a>to mediate navigation <em>away</em> from the current route.</p></li><li><p translation-result="on">用<a href="api/router/Resolve"><code>Resolve</code></a>在路由激活<em>之前</em>获取路由数据。</p><p translation-origin="off"><a href="api/router/Resolve"><code>Resolve</code></a>to perform route data retrieval <em>before</em> route activation.</p></li><li><p translation-result="on">用<a href="api/router/CanLoad"><code>CanLoad</code></a>来处理<em>异步</em>导航到某特性模块的情况。</p><p translation-origin="off"><a href="api/router/CanLoad"><code>CanLoad</code></a>to mediate navigation <em>to</em> a feature module loaded <em>asynchronously</em>.</p></li></ul><p translation-result="on">在分层路由的每个级别上，你都可以设置多个守卫。 路由器会先按照从最深的子路由由下往上检查的顺序来检查 <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a>()</code> 和 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a>()</code> 守卫。 然后它会按照从上到下的顺序检查 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a>()</code> 守卫。 如果特性模块是异步加载的，在加载它之前还会检查 <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a>()</code> 守卫。 如果<em>任何</em>一个守卫返回 <code>false</code>，其它尚未完成的守卫会被取消，这样整个导航就被取消了。</p><p translation-origin="off">You can have multiple guards at every level of a routing hierarchy. The router checks the <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> and <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> guards first, from the deepest child route to the top. Then it checks the <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> guards from the top down to the deepest child route. If the feature module is loaded asynchronously, the <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> guard is checked before the module is loaded. If <em>any</em> guard returns false, pending guards that have not completed will be canceled, and the entire navigation is canceled.</p><p translation-result="on">接下来的小节中有一些例子。</p><p translation-origin="off">There are several examples over the next few sections.</p><a id="can-activate-guard"></a><h3 id="canactivate-requiring-authentication" translation-result="on"><em>CanActivate</em>: 要求认证<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canactivate-requiring-authentication"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="canactivate-requiring-authentication"><em>CanActivate</em>: requiring authentication<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canactivate-requiring-authentication"><i class="material-icons">link</i></a></h3><p translation-result="on">应用程序通常会根据访问者来决定是否授予某个特性区的访问权。 你可以只对已认证过的用户或具有特定角色的用户授予访问权，还可以阻止或限制用户访问权，直到用户账户激活为止。</p><p translation-origin="off">Applications often restrict access to a feature area based on who the user is. You could permit access only to authenticated users or to users with a specific role. You might block or limit access until the user's account is activated.</p><p translation-result="on"><code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> 守卫是一个管理这些导航类业务规则的工具。</p><p translation-origin="off">The <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> guard is the tool to manage these navigation business rules.</p><h4 id="add-an-admin-feature-module" translation-result="on">添加一个“管理”特性模块<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-an-admin-feature-module"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="add-an-admin-feature-module">Add an admin feature module<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-an-admin-feature-module"><i class="material-icons">link</i></a></h4><p translation-result="on">在下一节，你将会使用一些新的<em>管理</em>特性来扩展危机中心。 那些特性尚未定义，但是你可以先从添加一个名叫 <code>AdminModule</code> 的特性模块开始。</p><p translation-origin="off">In this next section, you'll extend the crisis center with some new <em>administrative</em> features. Those features aren't defined yet. But you can start by adding a new feature module named <code>AdminModule</code>.</p><p translation-result="on">生成一个带有特性模块文件和路由配置文件的 <code>admin</code> 目录。</p><p translation-origin="off">Generate an <code>admin</code> folder with a feature module file and a routing configuration file.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate module admin --routing</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate </span><span class="kwd">module</span><span class="pln"> admin </span><span class="pun">--</span><span class="pln">routing</span></code>
    </pre></aio-code></code-example><p translation-result="on">接下来，生成一些支持性组件。</p><p translation-origin="off">Next, generate the supporting components.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component admin/admin-dashboard</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component admin</span><span class="pun">/</span><span class="pln">admin</span><span class="pun">-</span><span class="pln">dashboard</span></code>
    </pre></aio-code></code-example><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component admin/admin</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component admin</span><span class="pun">/</span><span class="pln">admin</span></code>
    </pre></aio-code></code-example><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component admin/manage-crises</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component admin</span><span class="pun">/</span><span class="pln">manage</span><span class="pun">-</span><span class="pln">crises</span></code>
    </pre></aio-code></code-example><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component admin/manage-heroes</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component admin</span><span class="pun">/</span><span class="pln">manage</span><span class="pun">-</span><span class="pln">heroes</span></code>
    </pre></aio-code></code-example><p translation-result="on">管理特性区的文件是这样的：</p><p translation-origin="off">The admin feature file structure looks like this:</p><div class="filetree"><div class="file"><p>src/app/admin</p></div><div class="children"><div class="file">admin</div><div class="children"><div class="file">admin.component.css</div><div class="file">admin.component.html</div><div class="file">admin.component.ts</div></div><div class="file">admin-dashboard</div><div class="children"><div class="file">admin-dashboard.component.css</div><div class="file">admin-dashboard.component.html</div><div class="file">admin-dashboard.component.ts</div></div><div class="file">manage-crises</div><div class="children"><div class="file">manage-crises.component.css</div><div class="file">manage-crises.component.html</div><div class="file">manage-crises.component.ts</div></div><div class="file">manage-heroes</div><div class="children"><div class="file">manage-heroes.component.css</div><div class="file">manage-heroes.component.html</div><div class="file">manage-heroes.component.ts</div></div><div class="file">admin.module.ts</div><div class="file">admin-routing.module.ts</div></div></div><p translation-result="on">管理特性模块包含 <code>AdminComponent</code>，它用于在特性模块内的仪表盘路由以及两个尚未完成的用于管理危机和英雄的组件之间进行路由。</p><p translation-origin="off">The admin feature module contains the <code>AdminComponent</code> used for routing within the feature module, a dashboard route and two unfinished components to manage crises and heroes.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="src/app/admin/admin/admin.component.html" path="router/src/app/admin/admin/admin.component.html">&lt;h3&gt;ADMIN&lt;/h3&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="./" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active" [<a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor">routerLinkActiveOptions</a>]="{ exact: true }"&gt;Dashboard&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="./crises" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Manage Crises&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="./heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Manage Heroes&lt;/a&gt; &lt;/nav&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code-pane><code-pane header="src/app/admin/admin-dashboard/admin-dashboard.component.html" path="router/src/app/admin/admin-dashboard/admin-dashboard.component.1.html">&lt;p&gt;Dashboard&lt;/p&gt;</code-pane><code-pane header="src/app/admin/admin.module.ts" path="router/src/app/admin/admin.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { AdminComponent } from './admin/admin.component'; import { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component'; import { ManageCrisesComponent } from './manage-crises/manage-crises.component'; import { ManageHeroesComponent } from './manage-heroes/manage-heroes.component'; import { AdminRoutingModule } from './admin-routing.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, AdminRoutingModule ], declarations: [ AdminComponent, AdminDashboardComponent, ManageCrisesComponent, ManageHeroesComponent ] }) export class AdminModule {}</code-pane><code-pane header="src/app/admin/manage-crises/manage-crises.component.html" path="router/src/app/admin/manage-crises/manage-crises.component.html">&lt;p&gt;Manage your crises here&lt;/p&gt;</code-pane><code-pane header="src/app/admin/manage-heroes/manage-heroes.component.html" path="router/src/app/admin/manage-heroes/manage-heroes.component.html">&lt;p&gt;Manage your heroes here&lt;/p&gt;</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-5-0" tabindex="0" aria-posinset="1" aria-setsize="5" aria-controls="mat-tab-content-5-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/admin/admin/admin.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-5-1" tabindex="-1" aria-posinset="2" aria-setsize="5" aria-controls="mat-tab-content-5-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/admin/admin-dashboard/admin-dashboard.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-5-2" tabindex="-1" aria-posinset="3" aria-setsize="5" aria-controls="mat-tab-content-5-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/admin/admin.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-5-3" tabindex="-1" aria-posinset="4" aria-setsize="5" aria-controls="mat-tab-content-5-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/admin/manage-crises/manage-crises.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-5-4" tabindex="-1" aria-posinset="5" aria-setsize="5" aria-controls="mat-tab-content-5-4" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/admin/manage-heroes/manage-heroes.component.html</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:323px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-29 mat-tab-body-active ng-star-inserted" id="mat-tab-content-5-0" aria-labelledby="mat-tab-label-5-0"><div class="mat-tab-body-content ng-tns-c50-29 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin/admin.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h3&gt;</span><span class="pln">ADMIN</span><span class="tag">&lt;/h3&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"./"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="pln">
    [</span><a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor"><span class="atn">routerLinkActiveOptions</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"{ exact: true }"</span><span class="tag">&gt;</span><span class="pln">Dashboard</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"./crises"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Manage Crises</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"./heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Manage Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-30 ng-star-inserted" id="mat-tab-content-5-1" aria-labelledby="mat-tab-label-5-1"><div class="mat-tab-body-content ng-tns-c50-30 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-31 ng-star-inserted" id="mat-tab-content-5-2" aria-labelledby="mat-tab-label-5-2"><div class="mat-tab-body-content ng-tns-c50-31 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-32 ng-star-inserted" id="mat-tab-content-5-3" aria-labelledby="mat-tab-label-5-3"><div class="mat-tab-body-content ng-tns-c50-32 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-33 ng-star-inserted" id="mat-tab-content-5-4" aria-labelledby="mat-tab-label-5-4"><div class="mat-tab-body-content ng-tns-c50-33 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><div class="alert is-helpful"><p translation-result="on">虽然管理仪表盘中的 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 只包含一个没有其它 URL 段的斜杠 <code>/</code>，但它能匹配管理特性区下的任何路由。 但你只希望在访问 <code>Dashboard</code> 路由时才激活该链接。 往 <code>Dashboard</code> 这个 routerLink 上添加另一个绑定 <code>[<a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor">routerLinkActiveOptions</a>]="{ exact: true }"</code>， 这样就只有当用户导航到 <code>/admin</code> 这个 URL 时才会激活它，而不会在导航到它的某个子路由时。</p><p translation-origin="off">Although the admin dashboard <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> only contains a relative slash without an additional URL segment, it is considered a match to any route within the admin feature area. You only want the <code>Dashboard</code> link to be active when the user visits that route. Adding an additional binding to the <code>Dashboard</code> routerLink,<code>[<a href="api/router/RouterLinkActive#routerLinkActiveOptions" class="code-anchor">routerLinkActiveOptions</a>]="{ exact: true }"</code>, marks the <code>./</code> link as active when the user navigates to the <code>/admin</code> URL and not when navigating to any of the child routes.</p></div><a id="component-less-route"></a><h5 id="component-less-route-grouping-routes-without-a-component" translation-result="on">无组件路由：分组路由，而不需要组件<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#component-less-route-grouping-routes-without-a-component"><i class="material-icons">link</i></a></h5><h5 translation-origin="off" id="component-less-route-grouping-routes-without-a-component">Component-less route: grouping routes without a component<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#component-less-route-grouping-routes-without-a-component"><i class="material-icons">link</i></a></h5><p translation-result="on">最初的管理路由配置如下：</p><p translation-origin="off">The initial admin routing configuration:</p><code-example path="router/src/app/admin/admin-routing.module.1.ts" header="src/app/admin/admin-routing.module.ts (admin routing)" region="admin-routes" ng-version="9.0.0-rc.11"><div style="display:none">const adminRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'admin', component: AdminComponent, children: [ { path: '', children: [ { path: 'crises', component: ManageCrisesComponent }, { path: 'heroes', component: ManageHeroesComponent }, { path: '', component: AdminDashboardComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(adminRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AdminRoutingModule {}</div><header class="ng-star-inserted">src/app/admin/admin-routing.module.ts (admin routing)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin-routing.module.ts (admin routing)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">const</span><span class="pln"> adminRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminComponent</span><span class="pun">,</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crises'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageCrisesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageHeroesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminDashboardComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">adminRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AdminRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><p translation-result="on">来看 <code>AdminComponent</code> 下的子路由，这里有一个带 <strong>path</strong> 和 <strong>children</strong> 的子路由， 但它没有使用 <strong>component</strong>。这并不是配置中的失误，而是在使用<strong>无组件</strong>路由。</p><p translation-origin="off">Looking at the child route under the <code>AdminComponent</code>, there is a <code>path</code> and a <code>children</code> property but it's not using a <code>component</code>. You haven't made a mistake in the configuration. You've defined a <em>component-less</em> route.</p><p translation-result="on">这里的目标是对 <code>admin</code> 路径下的 <code>危机中心</code> 管理类路由进行分组，但并不需要另一个仅用来分组路由的组件。 一个<em>无组件</em>的路由能让<a href="guide/router#can-activate-child-guard">守卫子路由</a>变得更容易。</p><p translation-origin="off">The goal is to group the <code>Crisis Center</code> management routes under the <code>admin</code> path. You don't need a component to do it. A <em>component-less</em> route makes it easier to <a href="guide/router#can-activate-child-guard">guard child routes</a>.</p><p translation-result="on">接下来，把 <code>AdminModule</code> 导入到 <code>app.module.ts</code> 中，并把它加入 <code>imports</code> 数组中来注册这些管理类路由。</p><p translation-origin="off">Next, import the <code>AdminModule</code> into <code>app.module.ts</code> and add it to the <code>imports</code> array to register the admin routes.</p><code-example path="router/src/app/app.module.4.ts" header="src/app/app.module.ts (admin module)" region="admin-module" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { CrisisCenterModule } from './crisis-center/crisis-center.module'; import { AdminModule } from './admin/admin.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, CrisisCenterModule, AdminModule, AppRoutingModule ], declarations: [ AppComponent, ComposeMessageComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts (admin module)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (admin module)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/common'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./compose-message/compose-message.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">        </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app-routing.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroesModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./heroes/heroes.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-center.module'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AdminModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./admin/admin.module'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/common/CommonModule" class="code-anchor"><span class="typ">CommonModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroesModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">CrisisCenterModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AdminModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AppRoutingModule</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">ComposeMessageComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">然后往壳组件 <code>AppComponent</code> 中添加一个链接，让用户能点击它，以访问该特性。</p><p translation-origin="off">Add an "Admin" link to the <code>AppComponent</code> shell so that users can get to this feature.</p><code-example path="router/src/app/app.component.5.html" header="src/app/app.component.html (template)" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h1 class="title"&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/heroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/admin" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Admin&lt;/a&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt; &lt;/nav&gt; &lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> name="popup"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/app.component.html (template)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html (template)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/heroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/admin"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Admin</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"[{ outlets: { popup: ['compose'] } }]"</span><span class="tag">&gt;</span><span class="pln">Contact</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> [@</span><span class="atn">routeAnimation</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"getAnimationData(routerOutlet)"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> #</span><span class="atn">routerOutlet</span><span class="pun">=</span><span class="atv">"outlet"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"popup"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><a id="guard-admin-feature"></a><h4 id="guard-the-admin-feature" translation-result="on">守护“管理特性”区<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#guard-the-admin-feature"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="guard-the-admin-feature">Guard the admin feature<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#guard-the-admin-feature"><i class="material-icons">link</i></a></h4><p translation-result="on">现在“危机中心”的每个路由都是对所有人开放的。这些新的<em>管理特性</em>应该只能被已登录用户访问。</p><p translation-origin="off">Currently every route within the <em>Crisis Center</em> is open to everyone. The new <em>admin</em> feature should be accessible only to authenticated users.</p><p translation-result="on">你可以在用户登录之前隐藏这些链接，但这样会有点复杂并难以维护。</p><p translation-origin="off">You could hide the link until the user logs in. But that's tricky and difficult to maintain.</p><p translation-result="on">你可以换种方式：写一个 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a>()</code> 守卫，将正在尝试访问管理组件匿名用户重定向到登录页。</p><p translation-origin="off">Instead you'll write a <code><a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>()</code> guard method to redirect anonymous users to the login page when they try to enter the admin area.</p><p translation-result="on">这是一个通用的守卫（你可以假设另外一些特性区也要求已认证过的用户才能访问），所以你可以在 <code>auth</code> 目录下生成一个 <code>AuthGuard</code>。</p><p translation-origin="off">This is a general purpose guard—you can imagine other features that require authenticated users—so you generate an <code>AuthGuard</code> in the <code>auth</code> folder.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate guard auth/auth</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate guard auth</span><span class="pun">/</span><span class="pln">auth</span></code>
    </pre></aio-code></code-example><p translation-result="on">此刻，你的兴趣在于看看守卫是如何工作的，所以第一个版本没做什么有用的事情。它只是往控制台写日志，并且立即返回 <code>true</code>，让导航继续：</p><p translation-origin="off">At the moment you're interested in seeing how guards work so the first version does nothing useful. It simply logs to console and <code>returns</code> true immediately, allowing navigation to proceed:</p><code-example path="router/src/app/auth/auth.guard.1.ts" header="src/app/auth/auth.guard.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a> } from '@angular/router'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthGuard implements <a href="api/router/CanActivate" class="code-anchor">CanActivate</a> { <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>( next: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { console.log('AuthGuard#<a href="api/router/Route#canActivate" class="code-anchor">canActivate</a> called'); return true; } }</div><header class="ng-star-inserted">src/app/auth/auth.guard.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.guard.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">(</span><span class="pln">
    </span><span class="kwd">next</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'AuthGuard#</span><a href="api/router/Route#canActivate" class="code-anchor"><span class="str">canActivate</span></a><span class="str"> called'</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">接下来，打开 <code>admin-routing.module.ts</code>，导入 <code>AuthGuard</code> 类，修改管理路由并通过 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a>()</code> 守卫来引用 <code>AuthGuard</code>：</p><p translation-origin="off">Next, open <code>admin-routing.module.ts</code>, import the <code>AuthGuard</code> class, and update the admin route with a <code><a href="api/router/Route#canActivate" class="code-anchor">canActivate</a></code> guard property that references it:</p><code-example path="router/src/app/admin/admin-routing.module.2.ts" header="src/app/admin/admin-routing.module.ts (guarded admin route)" region="admin-route" ng-version="9.0.0-rc.11"><div style="display:none">import { AuthGuard } from '../auth/auth.guard'; const adminRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'admin', component: AdminComponent, <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>: [AuthGuard], children: [ { path: '', children: [ { path: 'crises', component: ManageCrisesComponent }, { path: 'heroes', component: ManageHeroesComponent }, { path: '', component: AdminDashboardComponent } ], } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(adminRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AdminRoutingModule {}</div><header class="ng-star-inserted">src/app/admin/admin-routing.module.ts (guarded admin route)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin-routing.module.ts (guarded admin route)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="pun">}</span><span class="pln">                </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../auth/auth.guard'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> adminRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminComponent</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">AuthGuard</span><span class="pun">],</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crises'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageCrisesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageHeroesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminDashboardComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">],</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">adminRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AdminRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><p translation-result="on">管理特性区现在受此守卫保护了，不过这样的保护还不够。</p><p translation-origin="off">The admin feature is now protected by the guard, albeit protected poorly.</p><a id="teach-auth"></a><h4 id="teach-authguard-to-authenticate" translation-result="on">教 <em>AuthGuard</em> 进行认证<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#teach-authguard-to-authenticate"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="teach-authguard-to-authenticate">Teach <em>AuthGuard</em> to authenticate<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#teach-authguard-to-authenticate"><i class="material-icons">link</i></a></h4><p translation-result="on">先让 <code>AuthGuard</code> 至少能“假装”进行认证。</p><p translation-origin="off">Make the <code>AuthGuard</code> at least pretend to authenticate.</p><p translation-result="on"><code>AuthGuard</code> 可以调用应用中的一项服务，该服务能让用户登录，并且保存当前用户的信息。在 <code>admin</code> 目录下生成一个新的 <code>AuthService</code>：</p><p translation-origin="off">The <code>AuthGuard</code> should call an application service that can login a user and retain information about the current user. Generate a new <code>AuthService</code> in the <code>auth</code> folder:</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate service auth/auth</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate service auth</span><span class="pun">/</span><span class="pln">auth</span></code>
    </pre></aio-code></code-example><p translation-result="on">修改 <code>AuthService</code> 以登入此用户：</p><p translation-origin="off">Update the <code>AuthService</code> to log in the user:</p><code-example path="router/src/app/auth/auth.service.ts" header="src/app/auth/auth.service.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { Observable, of } from 'rxjs'; import { tap, delay } from 'rxjs/operators'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthService { isLoggedIn = false; // store the <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> so we can redirect after logging in redirectUrl: string; login(): Observable&lt;boolean&gt; { return of(true).pipe( delay(1000), tap(val =&gt; this.isLoggedIn = true) ); } logout(): void { this.isLoggedIn = false; } }</div><header class="ng-star-inserted">src/app/auth/auth.service.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.service.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">,</span><span class="pln"> of </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> tap</span><span class="pun">,</span><span class="pln"> delay </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  isLoggedIn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

  </span><span class="com">// store the </span><a href="api/core/SecurityContext#URL" class="code-anchor"><span class="com">URL</span></a><span class="com"> so we can redirect after logging in</span><span class="pln">
  redirectUrl</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">;</span><span class="pln">

  login</span><span class="pun">():</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> of</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">).</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">
      delay</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">),</span><span class="pln">
      tap</span><span class="pun">(</span><span class="pln">val </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">isLoggedIn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  logout</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">isLoggedIn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">虽然它不会真的进行登录，但足够让你进行这个讨论了。 它有一个 <code>isLoggedIn</code> 标志，用来标识是否用户已经登录过了。 它的 <code>login</code> 方法会仿真一个对外部服务的 API 调用，返回一个可观察对象（observable）。在短暂的停顿之后，这个可观察对象就会解析成功。 <code>redirectUrl</code> 属性将会保存在 URL 中，以便认证完之后导航到它。</p><p translation-origin="off">Although it doesn't actually log in, it has what you need for this discussion. It has an <code>isLoggedIn</code> flag to tell you whether the user is authenticated. Its <code>login</code> method simulates an API call to an external service by returning an observable that resolves successfully after a short pause. The <code>redirectUrl</code> property will store the attempted URL so you can navigate to it after authenticating.</p><p translation-result="on">这就修改 <code>AuthGuard</code> 来调用它。</p><p translation-origin="off">Revise the <code>AuthGuard</code> to call it.</p><code-example path="router/src/app/auth/auth.guard.2.ts" header="src/app/auth/auth.guard.ts (v2)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/Router" class="code-anchor">Router</a> } from '@angular/router'; import { AuthService } from './auth.service'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthGuard implements <a href="api/router/CanActivate" class="code-anchor">CanActivate</a> { constructor(private authService: AuthService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>( next: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { let url: string = state.url; return this.checkLogin(url); } checkLogin(url: string): boolean { if (this.authService.isLoggedIn) { return true; } // Store the attempted <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> for redirecting this.authService.redirectUrl = url; // Navigate to the login page with extras this.router.navigate(['/login']); return false; } }</div><header class="ng-star-inserted">src/app/auth/auth.guard.ts (v2)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.guard.ts (v2)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth.service'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> authService</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">(</span><span class="pln">
    </span><span class="kwd">next</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> state</span><span class="pun">.</span><span class="pln">url</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">isLoggedIn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// Store the attempted </span><a href="api/core/SecurityContext#URL" class="code-anchor"><span class="com">URL</span></a><span class="com"> for redirecting</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">redirectUrl </span><span class="pun">=</span><span class="pln"> url</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// Navigate to the login page with extras</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/login'</span><span class="pun">]);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意，你把 <code>AuthService</code> 和 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务<em>注入到</em>构造函数中。 你还没有提供 <code>AuthService</code>，这里要说明的是：可以往路由守卫中注入有用的服务。</p><p translation-origin="off">Notice that you <em>inject</em> the <code>AuthService</code> and the <code><a href="api/router/Router" class="code-anchor">Router</a></code> in the constructor. You haven't provided the <code>AuthService</code> yet but it's good to know that you can inject helpful services into routing guards.</p><p translation-result="on">该守卫返回一个同步的布尔值。如果用户已经登录，它就返回 <code>true</code>，导航会继续。</p><p translation-origin="off">This guard returns a synchronous boolean result. If the user is logged in, it returns true and the navigation continues.</p><p translation-result="on">这个 <code><a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a></code> 包含了<em>即将</em>被激活的路由，而 <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code> 包含了该应用<em>即将</em>到达的状态。 你应该通过守卫进行检查。</p><p translation-origin="off">The <code><a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a></code> contains the <em>future</em> route that will be activated and the <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code> contains the <em>future</em> <code><a href="api/router/RouterState" class="code-anchor">RouterState</a></code> of the application, should you pass through the guard check.</p><p translation-result="on">如果用户还没有登录，你就会用 <code><a href="api/router/RouterStateSnapshot#url" class="code-anchor">RouterStateSnapshot.url</a></code> 保存用户来自的 URL 并让路由器导航到登录页（你尚未创建该页）。 这间接导致路由器自动中止了这次导航，<code>checkLogin()</code> 返回 <code>false</code> 并不是必须的，但这样可以更清楚的表达意图。</p><p translation-origin="off">If the user is not logged in, you store the attempted URL the user came from using the <code><a href="api/router/RouterStateSnapshot#url" class="code-anchor">RouterStateSnapshot.url</a></code> and tell the router to navigate to a login page—a page you haven't created yet. This secondary navigation automatically cancels the current navigation; <code>checkLogin()</code> returns <code>false</code> just to be clear about that.</p><a id="add-login-component"></a><h4 id="add-the-logincomponent" translation-result="on">添加 <em>LoginComponent</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-the-logincomponent"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="add-the-logincomponent">Add the <em>LoginComponent</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#add-the-logincomponent"><i class="material-icons">link</i></a></h4><p translation-result="on">你需要一个 <code>LoginComponent</code> 来让用户登录进这个应用。在登录之后，你就会跳转到前面保存的 URL，如果没有，就跳转到默认 URL。 该组件没有什么新内容，你把它放进路由配置的方式也没什么新意。</p><p translation-origin="off">You need a <code>LoginComponent</code> for the user to log in to the app. After logging in, you'll redirect to the stored URL if available, or use the default URL. There is nothing new about this component or the way you wire it into the router configuration.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate component auth/login</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component auth</span><span class="pun">/</span><span class="pln">login</span></code>
    </pre></aio-code></code-example><p translation-result="on">在 <code>auth/auth-routing.module.ts</code> 文件中注册一个 <code>/login</code> 路由。在 <code>app.module.ts</code> 中，导入 <code>AuthModule</code> 并且添加到 <code>AppModule</code> 的 <code>imports</code> 中。</p><p translation-origin="off">Register a <code>/login</code> route in the <code>auth/auth-routing.module.ts</code>. In <code>app.module.ts</code>, import and add the <code>AuthModule</code> to the <code>AppModule</code> imports.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="src/app/app.module.ts" path="router/src/app/app.module.ts" region="auth">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { AuthModule } from './auth/auth.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, AuthModule, AppRoutingModule, ], declarations: [ AppComponent, ComposeMessageComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</code-pane><code-pane header="src/app/auth/login/login.component.html" path="router/src/app/auth/login/login.component.html">&lt;h2&gt;LOGIN&lt;/h2&gt; &lt;p&gt;{{<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>}}&lt;/p&gt; &lt;p&gt; &lt;button (click)="login()" *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="!authService.isLoggedIn"&gt;Login&lt;/button&gt; &lt;button (click)="logout()" *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="authService.isLoggedIn"&gt;Logout&lt;/button&gt; &lt;/p&gt;</code-pane><code-pane header="src/app/auth/login/login.component.ts" path="router/src/app/auth/login/login.component.1.ts">import { <a href="api/core/Component" class="code-anchor">Component</a> } from '@angular/core'; import { <a href="api/router/Router" class="code-anchor">Router</a> } from '@angular/router'; import { AuthService } from '../auth.service'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-login', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './login.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./login.component.css'] }) export class LoginComponent { <a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>: string; constructor(public authService: AuthService, public router: <a href="api/router/Router" class="code-anchor">Router</a>) { this.setMessage(); } setMessage() { this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out'); } login() { this.message = 'Trying to <a href="api/animations/browser/testing/MockAnimationDriver#log" class="code-anchor">log</a> in ...'; this.authService.login().subscribe(() =&gt; { this.setMessage(); if (this.authService.isLoggedIn) { // Get the redirect <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> from our auth service // If no redirect has been set, use the default let redirect = this.authService.redirectUrl ? this.router.parseUrl(this.authService.redirectUrl) : '/admin'; // Redirect the user this.router.navigateByUrl(redirect); } }); } logout() { this.authService.logout(); this.setMessage(); } }</code-pane><code-pane header="src/app/auth/auth.module.ts" path="router/src/app/auth/auth.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/common/CommonModule" class="code-anchor">CommonModule</a> } from '@angular/common'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { LoginComponent } from './login/login.component'; import { AuthRoutingModule } from './auth-routing.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/common/CommonModule" class="code-anchor">CommonModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, AuthRoutingModule ], declarations: [ LoginComponent ] }) export class AuthModule {}</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-6-0" tabindex="0" aria-posinset="1" aria-setsize="4" aria-controls="mat-tab-content-6-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/app.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-6-1" tabindex="-1" aria-posinset="2" aria-setsize="4" aria-controls="mat-tab-content-6-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/auth/login/login.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-6-2" tabindex="-1" aria-posinset="3" aria-setsize="4" aria-controls="mat-tab-content-6-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/auth/login/login.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-6-3" tabindex="-1" aria-posinset="4" aria-setsize="4" aria-controls="mat-tab-content-6-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">src/app/auth/auth.module.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:186px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-34 mat-tab-body-active ng-star-inserted" id="mat-tab-content-6-0" aria-labelledby="mat-tab-label-6-0"><div class="mat-tab-body-content ng-tns-c50-34 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser/animations'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./compose-message/compose-message.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">        </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app-routing.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroesModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./heroes/heroes.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">              </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth/auth.module'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroesModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AuthModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AppRoutingModule</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">ComposeMessageComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-35 ng-star-inserted" id="mat-tab-content-6-1" aria-labelledby="mat-tab-label-6-1"><div class="mat-tab-body-content ng-tns-c50-35 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-36 ng-star-inserted" id="mat-tab-content-6-2" aria-labelledby="mat-tab-label-6-2"><div class="mat-tab-body-content ng-tns-c50-36 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-37 ng-star-inserted" id="mat-tab-content-6-3" aria-labelledby="mat-tab-label-6-3"><div class="mat-tab-body-content ng-tns-c50-37 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><a id="can-activate-child-guard"></a><h3 id="canactivatechild-guarding-child-routes" translation-result="on"><code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code>：保护子路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canactivatechild-guarding-child-routes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="canactivatechild-guarding-child-routes"><em>CanActivateChild</em>: guarding child routes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canactivatechild-guarding-child-routes"><i class="material-icons">link</i></a></h3><p translation-result="on">你还可以使用 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 守卫来保护子路由。 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 守卫和 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> 守卫很像。 它们的区别在于，<code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 会在<em>任何子路由</em>被激活之前运行。</p><p translation-origin="off">You can also protect child routes with the <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> guard. The <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> guard is similar to the <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> guard. The key difference is that it runs <em>before</em> any child route is activated.</p><p translation-result="on">你要保护管理特性模块，防止它被非授权访问，还要保护这个特性模块<em>内部</em>的那些子路由。</p><p translation-origin="off">You protected the admin feature module from unauthorized access. You should also protect child routes <em>within</em> the feature module.</p><p translation-result="on">扩展 <code>AuthGuard</code> 以便在 <code>admin</code> 路由之间导航时提供保护。 打开 <code>auth.guard.ts</code> 并从路由库中导入 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 接口。</p><p translation-origin="off">Extend the <code>AuthGuard</code> to protect when navigating between the <code>admin</code> routes. Open <code>auth.guard.ts</code> and add the <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> interface to the imported tokens from the router package.</p><p translation-result="on">接下来，实现 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 方法，它所接收的参数与 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> 方法一样：一个 <code><a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a></code> 和一个 <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code>。 <code><a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a></code> 方法可以返回 <code>Observable&lt;boolean&gt;</code> 或 <code>Promise&lt;boolean&gt;</code> 来支持异步检查，或 <code>boolean</code> 来支持同步检查。 这里返回的是 <code>boolean</code>：</p><p translation-origin="off">Next, implement the <code><a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>()</code> method which takes the same arguments as the <code><a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>()</code> method: an <code><a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a></code> and <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code>. The <code><a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>()</code> method can return an <code>Observable&lt;boolean&gt;</code> or <code>Promise&lt;boolean&gt;</code> for async checks and a <code>boolean</code> for sync checks. This one returns a <code>boolean</code>:</p><code-example path="router/src/app/auth/auth.guard.3.ts" header="src/app/auth/auth.guard.ts (excerpt)" region="can-activate-child" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a> } from '@angular/router'; import { AuthService } from './auth.service'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthGuard implements <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a> { constructor(private authService: AuthService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>( route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { let url: string = state.url; return this.checkLogin(url); } <a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>( route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { return this.canActivate(route, <a href="api/animations/state" class="code-anchor">state</a>); } /* . . . */ }</div><header class="ng-star-inserted">src/app/auth/auth.guard.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.guard.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln">                           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth.service'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> authService</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">(</span><span class="pln">
    route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> state</span><span class="pun">.</span><span class="pln">url</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><a href="api/router/Route#canActivateChild" class="code-anchor"><span class="pln">canActivateChild</span></a><span class="pun">(</span><span class="pln">
    route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">canActivate</span><span class="pun">(</span><span class="pln">route</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

</span><span class="com">/* . . . */</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">同样把这个 <code>AuthGuard</code> 添加到“无组件的”管理路由，来同时保护它的所有子路由，而不是为每个路由单独添加这个 <code>AuthGuard</code>。</p><p translation-origin="off">Add the same <code>AuthGuard</code> to the <code>component-less</code> admin route to protect all other child routes at one time instead of adding the <code>AuthGuard</code> to each route individually.</p><code-example path="router/src/app/admin/admin-routing.module.3.ts" header="src/app/admin/admin-routing.module.ts (excerpt)" region="can-activate-child" ng-version="9.0.0-rc.11"><div style="display:none">const adminRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'admin', component: AdminComponent, <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>: [AuthGuard], children: [ { path: '', <a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>: [AuthGuard], children: [ { path: 'crises', component: ManageCrisesComponent }, { path: 'heroes', component: ManageHeroesComponent }, { path: '', component: AdminDashboardComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(adminRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AdminRoutingModule {}</div><header class="ng-star-inserted">src/app/admin/admin-routing.module.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin-routing.module.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">const</span><span class="pln"> adminRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminComponent</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">AuthGuard</span><span class="pun">],</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        </span><a href="api/router/Route#canActivateChild" class="code-anchor"><span class="pln">canActivateChild</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">AuthGuard</span><span class="pun">],</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crises'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageCrisesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ManageHeroesComponent</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AdminDashboardComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">adminRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AdminRoutingModule</span><span class="pln"> </span><span class="pun">{}</span></code>
    </pre></aio-code></code-example><a id="can-deactivate-guard"></a><h3 id="candeactivate-handling-unsaved-changes" translation-result="on"><em>CanDeactivate</em>：处理未保存的更改<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#candeactivate-handling-unsaved-changes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="candeactivate-handling-unsaved-changes"><em>CanDeactivate</em>: handling unsaved changes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#candeactivate-handling-unsaved-changes"><i class="material-icons">link</i></a></h3><p translation-result="on">回到“Heroes”工作流，该应用毫不犹豫的接受对英雄的任何修改，不作任何校验。</p><p translation-origin="off">Back in the "Heroes" workflow, the app accepts every change to a hero immediately without hesitation or validation.</p><p translation-result="on">在现实世界中，你得先把用户的改动积累起来。 你可能不得不进行跨字段的校验，可能要找服务器进行校验，可能得把这些改动保存成一种待定状态，直到用户或者把这些改动<em>作为一组</em>进行确认或撤销所有改动。</p><p translation-origin="off">In the real world, you might have to accumulate the users changes. You might have to validate across fields. You might have to validate on the server. You might have to hold changes in a pending state until the user confirms them <em>as a group</em> or cancels and reverts all changes.</p><p translation-result="on">当用户要导航到外面时，该怎么处理这些既没有审核通过又没有保存过的改动呢？ 你不能马上离开，不在乎丢失这些改动的风险，那显然是一种糟糕的用户体验。</p><p translation-origin="off">What do you do about unapproved, unsaved changes when the user navigates away? You can't just leave and risk losing the user's changes; that would be a terrible experience.</p><p translation-result="on">最好能暂停，并让用户决定该怎么做。 如果用户选择了取消，你就留下来，并允许更多改动。 如果用户选择了确认，那就进行保存。</p><p translation-origin="off">It's better to pause and let the user decide what to do. If the user cancels, you'll stay put and allow more changes. If the user approves, the app can save.</p><p translation-result="on">在保存成功之前，你还可以继续推迟导航。如果你让用户立即移到下一个界面，而保存却失败了（可能因为数据不符合有效性规则），你就会丢失该错误的上下文环境。</p><p translation-origin="off">You still might delay navigation until the save succeeds. If you let the user move to the next screen immediately and the save were to fail (perhaps the data are ruled invalid), you would lose the context of the error.</p><p translation-result="on">在等待服务器的答复时，你没法阻塞它 —— 这在浏览器中是不可能的。 你只能用异步的方式在等待服务器答复之前先停止导航。</p><p translation-origin="off">You can't block while waiting for the server—that's not possible in a browser. You need to stop the navigation while you wait, asynchronously, for the server to return with its answer.</p><p translation-result="on">你需要 <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> 守卫。</p><p translation-origin="off">You need the <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> guard.</p><a id="cancel-save"></a><h4 id="cancel-and-save" translation-result="on">取消与保存<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#cancel-and-save"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="cancel-and-save">Cancel and save<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#cancel-and-save"><i class="material-icons">link</i></a></h4><p translation-result="on">这个范例应用不会与服务器通讯。 幸运的是，你有另一种方式来演示异步的路由器钩子。</p><p translation-origin="off">The sample application doesn't talk to a server. Fortunately, you have another way to demonstrate an asynchronous router hook.</p><p translation-result="on">用户在 <code>CrisisDetailComponent</code> 中更新危机信息。 与 <code>HeroDetailComponent</code> 不同，用户的改动不会立即更新危机的实体对象。当用户按下了 <em>Save</em> 按钮时，应用就更新这个实体对象；如果按了 <em>Cancel</em> 按钮，那就放弃这些更改。</p><p translation-origin="off">Users update crisis information in the <code>CrisisDetailComponent</code>. Unlike the <code>HeroDetailComponent</code>, the user changes do not update the crisis entity immediately. Instead, the app updates the entity when the user presses the <em>Save</em> button and discards the changes when the user presses the <em>Cancel</em> button.</p><p translation-result="on">这两个按钮都会在保存或取消之后导航回危机列表。</p><p translation-origin="off">Both buttons navigate back to the crisis list after save or cancel.</p><code-example path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts" header="src/app/crisis-center/crisis-detail/crisis-detail.component.ts (cancel and save methods)" region="cancel-save" ng-version="9.0.0-rc.11"><div style="display:none">cancel() { this.gotoCrises(); } save() { this.crisis.name = this.editName; this.gotoCrises(); }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail/crisis-detail.component.ts (cancel and save methods)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail/crisis-detail.component.ts (cancel and save methods)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">cancel</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">gotoCrises</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

save</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">crisis</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">editName</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">gotoCrises</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">如果用户尝试不保存或撤销就导航到外面该怎么办？ 用户可以按浏览器的后退按钮，或点击英雄的链接。 这些操作都会触发导航。本应用应该自动保存或取消吗？</p><p translation-origin="off">What if the user tries to navigate away without saving or canceling? The user could push the browser back button or click the heroes link. Both actions trigger a navigation. Should the app save or cancel automatically?</p><p translation-result="on">都不行。应用应该弹出一个确认对话框来要求用户明确做出选择，该对话框会<em>用异步的方式等用户做出选择</em>。</p><p translation-origin="off">This demo does neither. Instead, it asks the user to make that choice explicitly in a confirmation dialog box that <em>waits asynchronously for the user's answer</em>.</p><div class="alert is-helpful"><p translation-result="on">你也能用同步的方式等用户的答复，阻塞代码。但如果能用异步的方式等待用户的答复，应用就会响应性更好，也能同时做别的事。异步等待用户的答复和等待服务器的答复是类似的。</p><p translation-origin="off">You could wait for the user's answer with synchronous, blocking code. The app will be more responsive—and can do other work—by waiting for the user's answer asynchronously. Waiting for the user asynchronously is like waiting for the server asynchronously.</p></div><p translation-result="on">生成一个 <code>Dialog</code> 服务，以处理用户的确认操作。</p><p translation-origin="off">Generate a <code>Dialog</code> service to handle user confirmation.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate service dialog</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate service dialog</span></code>
    </pre></aio-code></code-example><p translation-result="on">为 <code>DialogService</code> 添加一个 <code>confirm()</code> 方法，以提醒用户确认。<code>window.confirm</code> 是一个<em>阻塞型</em>操作，它会显示一个模态对话框，并等待用户的交互。</p><p translation-origin="off">Add a <code>confirm()</code> method to the <code>DialogService</code> to prompt the user to confirm their intent. The <code>window.confirm</code> is a <em>blocking</em> action that displays a modal dialog and waits for user interaction.</p><code-example path="router/src/app/dialog.service.ts" header="src/app/dialog.service.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { Observable, of } from 'rxjs'; /** * Async modal dialog service * DialogService makes this app easier to test by faking this service. * TODO: better modal implementation that doesn't use window.confirm */ @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class DialogService { /** * Ask user to confirm an action. `<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>` explains the action and choices. * Returns observable resolving to `true`=confirm or `false`=cancel */ confirm(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>?: string): Observable&lt;boolean&gt; { const confirmation = window.confirm(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a> || 'Is it OK?'); return of(confirmation); }; }</div><header class="ng-star-inserted">src/app/dialog.service.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/dialog.service.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">,</span><span class="pln"> of </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">

</span><span class="com">/**
 * Async modal dialog service
 * DialogService makes this app easier to test by faking this service.
 * TODO: better modal implementation that doesn't use window.confirm
 */</span><span class="pln">
</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DialogService</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">/**
   * Ask user to confirm an action. `</span><a href="api/common/http/HttpErrorResponse#message" class="code-anchor"><span class="com">message</span></a><span class="com">` explains the action and choices.
   * Returns observable resolving to `true`=confirm or `false`=cancel
   */</span><span class="pln">
  confirm</span><span class="pun">(</span><a href="api/common/http/HttpErrorResponse#message" class="code-anchor"><span class="pln">message</span></a><span class="pun">?:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> confirmation </span><span class="pun">=</span><span class="pln"> window</span><span class="pun">.</span><span class="pln">confirm</span><span class="pun">(</span><a href="api/common/http/HttpErrorResponse#message" class="code-anchor"><span class="pln">message</span></a><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="str">'Is it OK?'</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> of</span><span class="pun">(</span><span class="pln">confirmation</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">它返回<em>observable</em>，当用户最终决定了如何去做时，它就会被<em>解析</em> —— 或者决定放弃更改直接导航离开（<code>true</code>），或者保留未完成的修改，留在危机编辑器中（<code>false</code>）。</p><p translation-origin="off">It returns an <code>Observable</code> that <em>resolves</em> when the user eventually decides what to do: either to discard changes and navigate away (<code>true</code>) or to preserve the pending changes and stay in the crisis editor (<code>false</code>).</p><a id="CanDeactivate"></a><p translation-result="on">生成一个<em>守卫（guard）</em>，以检查组件（任意组件均可）中是否存在 <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> 方法。</p><p translation-origin="off">Generate a <em>guard</em> that checks for the presence of a <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> method in a component—any component.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate guard can-deactivate</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate guard can</span><span class="pun">-</span><span class="pln">deactivate</span></code>
    </pre></aio-code></code-example><p translation-result="on">创建了一个 <code>Guard</code>，它将检查这个（任意）组件中是否有 <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> 函数。 <code>CrisisDetailComponent</code> 就会有这个方法。 但是该守卫并不需要知道 <code>CrisisDetailComponent</code> 确认退出激活状态的详情。 它只需要检查该组件是否有一个 <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> 方法，并调用它。 这就让该守卫可以复用。</p><p translation-origin="off">The <code>CrisisDetailComponent</code> will have this method. But the guard doesn't have to know that. The guard shouldn't know the details of any component's deactivation method. It need only detect that the component has a <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> method and call it. This approach makes the guard reusable.</p><code-example path="router/src/app/can-deactivate.guard.ts" header="src/app/can-deactivate.guard.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a> } from '@angular/router'; import { Observable } from 'rxjs'; export interface CanComponentDeactivate { <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: () =&gt; Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean; } @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CanDeactivateGuard implements <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a>&lt;CanComponentDeactivate&gt; { <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>(component: CanComponentDeactivate) { return component.canDeactivate ? component.canDeactivate() : true; } }</div><header class="ng-star-inserted">src/app/can-deactivate.guard.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/can-deactivate.guard.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/CanDeactivate" class="code-anchor"><span class="typ">CanDeactivate</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">interface</span><span class="pln"> </span><span class="typ">CanComponentDeactivate</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 </span><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Promise</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CanDeactivateGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanDeactivate" class="code-anchor"><span class="typ">CanDeactivate</span></a><span class="pun">&lt;</span><span class="typ">CanComponentDeactivate</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">(</span><span class="pln">component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CanComponentDeactivate</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> component</span><span class="pun">.</span><span class="pln">canDeactivate </span><span class="pun">?</span><span class="pln"> component</span><span class="pun">.</span><span class="pln">canDeactivate</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">另外，你也可以为 <code>CrisisDetailComponent</code> 创建一个特定的 <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> 守卫。 在需要访问外部信息时，<code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> 方法为你提供了组件、<code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> 和 <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code> 的当前实例。 如果只想为这个组件使用该守卫，并且需要获取该组件属性或确认路由器是否允许从该组件导航出去时，这会非常有用。</p><p translation-origin="off">Alternatively, you could make a component-specific <code><a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a></code> guard for the <code>CrisisDetailComponent</code>. The <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> method provides you with the current instance of the <code>component</code>, the current <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code>, and <code><a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a></code> in case you needed to access some external information. This would be useful if you only wanted to use this guard for this component and needed to get the component's properties or confirm whether the router should allow navigation away from it.</p><code-example path="router/src/app/can-deactivate.guard.1.ts" header="src/app/can-deactivate.guard.ts (component-specific)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { Observable } from 'rxjs'; import { <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a> } from '@angular/router'; import { CrisisDetailComponent } from './crisis-center/crisis-detail/crisis-detail.component'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CanDeactivateGuard implements <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a>&lt;CrisisDetailComponent&gt; { <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>( component: CrisisDetailComponent, route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a> ): Observable&lt;boolean&gt; | boolean { // Get the Crisis Center ID console.log(route.paramMap.get('id')); // Get the current <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> console.log(state.url); // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged if (!component.crisis || component.crisis.name === component.editName) { return true; } // Otherwise ask the user with the dialog service and return its // observable which resolves to true or false when the user decides return component.dialogService.confirm('Discard <a href="api/core/QueryList#changes" class="code-anchor">changes</a>?'); } }</div><header class="ng-star-inserted">src/app/can-deactivate.guard.ts (component-specific)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/can-deactivate.guard.ts (component-specific)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pln"> </span><span class="pun">}</span><span class="pln">           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/CanDeactivate" class="code-anchor"><span class="typ">CanDeactivate</span></a><span class="pun">,</span><span class="pln">
         </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
         </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-detail/crisis-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CanDeactivateGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanDeactivate" class="code-anchor"><span class="typ">CanDeactivate</span></a><span class="pun">&lt;</span><span class="typ">CrisisDetailComponent</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">(</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pun">,</span><span class="pln">
    route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pln">
  </span><span class="pun">):</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Get the Crisis Center ID</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">route</span><span class="pun">.</span><span class="pln">paramMap</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// Get the current </span><a href="api/core/SecurityContext#URL" class="code-anchor"><span class="com">URL</span></a><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">state</span><span class="pun">.</span><span class="pln">url</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">component</span><span class="pun">.</span><span class="pln">crisis </span><span class="pun">||</span><span class="pln"> component</span><span class="pun">.</span><span class="pln">crisis</span><span class="pun">.</span><span class="pln">name </span><span class="pun">===</span><span class="pln"> component</span><span class="pun">.</span><span class="pln">editName</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// Otherwise ask the user with the dialog service and return its</span><span class="pln">
    </span><span class="com">// observable which resolves to true or false when the user decides</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> component</span><span class="pun">.</span><span class="pln">dialogService</span><span class="pun">.</span><span class="pln">confirm</span><span class="pun">(</span><span class="str">'Discard </span><a href="api/core/QueryList#changes" class="code-anchor"><span class="str">changes</span></a><span class="str">?'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">看看 <code>CrisisDetailComponent</code> 组件，它已经实现了对未保存的更改进行确认的工作流。</p><p translation-origin="off">Looking back at the <code>CrisisDetailComponent</code>, it implements the confirmation workflow for unsaved changes.</p><code-example path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts" header="src/app/crisis-center/crisis-detail/crisis-detail.component.ts (excerpt)" region="canDeactivate" ng-version="9.0.0-rc.11"><div style="display:none"><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>(): Observable&lt;boolean&gt; | boolean { // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged if (!this.crisis || this.crisis.name === this.editName) { return true; } // Otherwise ask the user with the dialog service and return its // observable which resolves to true or false when the user decides return this.dialogService.confirm('Discard <a href="api/core/QueryList#changes" class="code-anchor">changes</a>?'); }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail/crisis-detail.component.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail/crisis-detail.component.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">():</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;boolean&gt;</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">crisis </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">crisis</span><span class="pun">.</span><span class="pln">name </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">editName</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="com">// Otherwise ask the user with the dialog service and return its</span><span class="pln">
  </span><span class="com">// observable which resolves to true or false when the user decides</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">dialogService</span><span class="pun">.</span><span class="pln">confirm</span><span class="pun">(</span><span class="str">'Discard </span><a href="api/core/QueryList#changes" class="code-anchor"><span class="str">changes</span></a><span class="str">?'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意，<code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a></code> 方法<em>可以</em>同步返回，如果没有危机，或者没有未定的修改，它就立即返回 <code>true</code>。但是它也可以返回一个承诺（<code>Promise</code>）或可观察对象（<code>Observable</code>），路由器将等待它们被解析为真值（继续导航）或假值（留下）。</p><p translation-origin="off">Notice that the <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>()</code> method <em>can</em> return synchronously; it returns <code>true</code> immediately if there is no crisis or there are no pending changes. But it can also return a <code>Promise</code> or an <code>Observable</code> and the router will wait for that to resolve to truthy (navigate) or falsy (stay put).</p><p translation-result="on">往 <code>crisis-center.routing.module.ts</code> 的危机详情路由中用 <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a></code> 数组添加一个 <code>Guard</code>（守卫）。</p><p translation-origin="off">Add the <code>Guard</code> to the crisis detail route in <code>crisis-center-routing.module.ts</code> using the <code><a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a></code> array property.</p><code-example path="router/src/app/crisis-center/crisis-center-routing.module.3.ts" header="src/app/crisis-center/crisis-center-routing.module.ts (can deactivate guard)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CanDeactivateGuard } from '../can-deactivate.guard'; const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent, <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: [CanDeactivateGuard] }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(crisisCenterRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class CrisisCenterRoutingModule { }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center-routing.module.ts (can deactivate guard)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center-routing.module.ts (can deactivate guard)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center-home/crisis-center-home.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-center.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-detail/crisis-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CanDeactivateGuard</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../can-deactivate.guard'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> crisisCenterRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pun">,</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">':id'</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pun">,</span><span class="pln">
            </span><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">CanDeactivateGuard</span><span class="pun">]</span><span class="pln">
          </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">crisisCenterRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisCenterRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">现在，你已经给了用户一个能保护未保存更改的安全守卫。</p><p translation-origin="off">Now you have given the user a safeguard against unsaved changes.</p><a id="Resolve"></a> <a id="resolve-guard"></a><h3 id="resolve-pre-fetching-component-data" translation-result="on"><em>Resolve</em>: 预先获取组件数据<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#resolve-pre-fetching-component-data"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="resolve-pre-fetching-component-data"><em>Resolve</em>: pre-fetching component data<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#resolve-pre-fetching-component-data"><i class="material-icons">link</i></a></h3><p translation-result="on">在 <code>Hero Detail</code> 和 <code>Crisis Detail</code> 中，它们等待路由读取完对应的英雄和危机。</p><p translation-origin="off">In the <code>Hero Detail</code> and <code>Crisis Detail</code>, the app waited until the route was activated to fetch the respective hero or crisis.</p><p translation-result="on">这种方式没有问题，但是它们还有进步的空间。 如果你在使用真实 api，很有可能数据返回有延迟，导致无法即时显示。 在这种情况下，直到数据到达前，显示一个空的组件不是最好的用户体验。</p><p translation-origin="off">This worked well, but there's a better way. If you were using a real world API, there might be some delay before the data to display is returned from the server. You don't want to display a blank component while waiting for the data.</p><p translation-result="on">最好预先从服务器上获取完数据，这样在路由激活的那一刻数据就准备好了。 还要在路由到此组件之前处理好错误。 但当某个 <code>id</code> 无法对应到一个危机详情时，就没办法处理它。 这时最好把用户带回到“危机列表”中，那里显示了所有有效的“危机”。</p><p translation-origin="off">It's preferable to pre-fetch data from the server so it's ready the moment the route is activated. This also allows you to handle errors before routing to the component. There's no point in navigating to a crisis detail for an <code>id</code> that doesn't have a record. It'd be better to send the user back to the <code>Crisis <a href="api/common/NumberSymbol#List" class="code-anchor">List</a></code> that shows only valid crisis centers.</p><p translation-result="on">总之，你希望的是只有当所有必要数据都已经拿到之后，才渲染这个路由组件。</p><p translation-origin="off">In summary, you want to delay rendering the routed component until all necessary data have been fetched.</p><p translation-result="on">你需要 <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> 守卫。</p><p translation-origin="off">You need a <em>resolver</em>.</p><a id="fetch-before-navigating"></a><h4 id="fetch-data-before-navigating" translation-result="on">导航前预先加载路由信息<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#fetch-data-before-navigating"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="fetch-data-before-navigating">Fetch data before navigating<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#fetch-data-before-navigating"><i class="material-icons">link</i></a></h4><p translation-result="on">目前，<code>CrisisDetailComponent</code> 会接收选中的危机。 如果该危机没有找到，它就会导航回危机列表视图。</p><p translation-origin="off">At the moment, the <code>CrisisDetailComponent</code> retrieves the selected crisis. If the crisis is not found, it navigates back to the crisis list view.</p><p translation-result="on">如果能在该路由将要激活时提前处理了这个问题，那么用户体验会更好。 <code>CrisisDetailResolver</code> 服务可以接收一个 <code>Crisis</code>，而如果这个 <code>Crisis</code> 不存在，就会在激活该路由并创建 <code>CrisisDetailComponent</code> 之前先行离开。</p><p translation-origin="off">The experience might be better if all of this were handled first, before the route is activated. A <code>CrisisDetailResolver</code> service could retrieve a <code>Crisis</code> or navigate away if the <code>Crisis</code> does not exist <em>before</em> activating the route and creating the <code>CrisisDetailComponent</code>.</p><p translation-result="on">在 <code>Crisis Center</code> 特性区生成一个 <code>CrisisDetailResolver</code> 服务文件。</p><p translation-origin="off">Generate a <code>CrisisDetailResolver</code> service file within the <code>Crisis Center</code> feature area.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate service crisis-center/crisis-detail-resolver</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate service crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">/</span><span class="pln">crisis</span><span class="pun">-</span><span class="pln">detail</span><span class="pun">-</span><span class="pln">resolver</span></code>
    </pre></aio-code></code-example><code-example path="router/src/app/crisis-center/crisis-detail-resolver.service.1.ts" header="src/app/crisis-center/crisis-detail-resolver.service.ts (generated)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CrisisDetailResolverService { constructor() { } }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail-resolver.service.ts (generated)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail-resolver.service.ts (generated)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisDetailResolverService</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">constructor</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">在 <code>CrisisDetailComponent.ngOnInit</code> 中拿到相关的危机检索逻辑，并且把它们移到 <code>CrisisDetailResolverService</code> 中。 导入 <code>Crisis</code> 模型、<code>CrisisService</code> 和 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 以便让你可以在找不到指定的危机时导航到别处。</p><p translation-origin="off">Take the relevant parts of the crisis retrieval logic in <code>CrisisDetailComponent.ngOnInit</code> and move them into the <code>CrisisDetailResolverService</code>. Import the <code>Crisis</code> model, <code>CrisisService</code>, and the <code><a href="api/router/Router" class="code-anchor">Router</a></code> so you can navigate elsewhere if you can't fetch the crisis.</p><p translation-result="on">为了更明确一点，可以实现一个带有 <code>Crisis</code> 类型的 <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> 接口。</p><p translation-origin="off">Be explicit. Implement the <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> interface with a type of <code>Crisis</code>.</p><p translation-result="on">注入 <code>CrisisService</code> 和 <code><a href="api/router/Router" class="code-anchor">Router</a></code>，并实现 <code><a href="api/core/ReflectiveInjector#resolve" class="code-anchor">resolve()</a></code> 方法。 该方法可以返回一个 <code>Promise</code>、一个 <code>Observable</code> 来支持异步方式，或者直接返回一个值来支持同步方式。</p><p translation-origin="off">Inject the <code>CrisisService</code> and <code><a href="api/router/Router" class="code-anchor">Router</a></code> and implement the <code><a href="api/core/ReflectiveInjector#resolve" class="code-anchor">resolve()</a></code> method. That method could return a <code>Promise</code>, an <code>Observable</code>, or a synchronous return value.</p><p translation-result="on"><code>CrisisService.getCrisis</code> 方法返回一个可观察对象，以防止在数据获取完之前加载本路由。 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 守卫要求这个可观察对象必须可结束（<code>complete</code>），也就是说它已经发出了所有值。 你可以为 <code>take</code> 操作符传入一个参数 <code>1</code>，以确保这个可观察对象会在从 <code>getCrisis</code> 方法所返回的可观察对象中取到第一个值之后就会结束。</p><p translation-origin="off">The <code>CrisisService.getCrisis</code> method returns an observable, in order to prevent the route from loading until the data is fetched. The <code><a href="api/router/Router" class="code-anchor">Router</a></code> guards require an observable to <code>complete</code>, meaning it has emitted all of its values. You use the <code>take</code> operator with an argument of <code>1</code> to ensure that the Observable completes after retrieving the first value from the Observable returned by the <code>getCrisis</code> method.</p><p translation-result="on">如果它没有返回有效的 <code>Crisis</code>，就会返回一个 <code>Observable</code>，以取消以前到 <code>CrisisDetailComponent</code> 的在途导航，并把用户导航回 <code>CrisisListComponent</code>。修改后的 <code><a href="api/router/OutletContext#resolver" class="code-anchor">resolver</a></code> 服务是这样的：</p><p translation-origin="off">If it doesn't return a valid <code>Crisis</code>, return an empty <code>Observable</code>, canceling the previous in-flight navigation to the <code>CrisisDetailComponent</code> and navigate the user back to the <code>CrisisListComponent</code>. The updated resolver service looks like this:</p><code-example path="router/src/app/crisis-center/crisis-detail-resolver.service.ts" header="src/app/crisis-center/crisis-detail-resolver.service.ts" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/Resolve" class="code-anchor">Resolve</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a> } from '@angular/router'; import { Observable, of, EMPTY } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; import { CrisisService } from './crisis.service'; import { Crisis } from './crisis'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CrisisDetailResolverService implements <a href="api/router/Resolve" class="code-anchor">Resolve</a>&lt;Crisis&gt; { constructor(private cs: CrisisService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#resolve" class="code-anchor">resolve</a>(route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): Observable&lt;Crisis&gt; | Observable&lt;never&gt; { let id = route.paramMap.get('id'); return this.cs.getCrisis(id).pipe( take(1), mergeMap(crisis =&gt; { if (crisis) { return of(crisis); } else { // id not found this.router.navigate(['/crisis-center']); return EMPTY; } }) ); } }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail-resolver.service.ts</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail-resolver.service.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Resolve" class="code-anchor"><span class="typ">Resolve</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln">                                 </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">,</span><span class="pln"> of</span><span class="pun">,</span><span class="pln"> EMPTY </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> mergeMap</span><span class="pun">,</span><span class="pln"> take </span><span class="pun">}</span><span class="pln">         </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis.service'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Crisis</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisDetailResolverService</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/Resolve" class="code-anchor"><span class="typ">Resolve</span></a><span class="pun">&lt;</span><span class="typ">Crisis</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> cs</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisService</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  </span><a href="api/router/Route#resolve" class="code-anchor"><span class="pln">resolve</span></a><span class="pun">(</span><span class="pln">route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">&lt;</span><span class="typ">Crisis</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;never&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> id </span><span class="pun">=</span><span class="pln"> route</span><span class="pun">.</span><span class="pln">paramMap</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">cs</span><span class="pun">.</span><span class="pln">getCrisis</span><span class="pun">(</span><span class="pln">id</span><span class="pun">).</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">
      take</span><span class="pun">(</span><span class="lit">1</span><span class="pun">),</span><span class="pln">
      mergeMap</span><span class="pun">(</span><span class="pln">crisis </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crisis</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          </span><span class="kwd">return</span><span class="pln"> of</span><span class="pun">(</span><span class="pln">crisis</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// id not found</span><span class="pln">
          </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/crisis-center'</span><span class="pun">]);</span><span class="pln">
          </span><span class="kwd">return</span><span class="pln"> EMPTY</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
      </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">把这个解析器（resolver）导入到 <code>crisis-center-routing.module.ts</code> 中，并往 <code>CrisisDetailComponent</code> 的路由配置中添加一个 <code><a href="api/router/Route#resolve" class="code-anchor">resolve</a></code> 对象。</p><p translation-origin="off">Import this resolver in the <code>crisis-center-routing.module.ts</code> and add a <code><a href="api/router/Route#resolve" class="code-anchor">resolve</a></code> object to the <code>CrisisDetailComponent</code> route configuration.</p><code-example path="router/src/app/crisis-center/crisis-center-routing.module.4.ts" header="src/app/crisis-center/crisis-center-routing.module.ts (resolver)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CanDeactivateGuard } from '../can-deactivate.guard'; import { CrisisDetailResolverService } from './crisis-detail-resolver.service'; const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent, <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: [CanDeactivateGuard], <a href="api/router/Route#resolve" class="code-anchor">resolve</a>: { crisis: CrisisDetailResolverService } }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(crisisCenterRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class CrisisCenterRoutingModule { }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-center-routing.module.ts (resolver)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-center-routing.module.ts (resolver)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center-home/crisis-center-home.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-list/crisis-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-center/crisis-center.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-detail/crisis-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CanDeactivateGuard</span><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../can-deactivate.guard'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">CrisisDetailResolverService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./crisis-detail-resolver.service'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> crisisCenterRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterComponent</span><span class="pun">,</span><span class="pln">
    children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisListComponent</span><span class="pun">,</span><span class="pln">
        children</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">':id'</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailComponent</span><span class="pun">,</span><span class="pln">
            </span><a href="api/router/Route#canDeactivate" class="code-anchor"><span class="pln">canDeactivate</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">CanDeactivateGuard</span><span class="pun">],</span><span class="pln">
            </span><a href="api/router/Route#resolve" class="code-anchor"><span class="pln">resolve</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
              crisis</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisDetailResolverService</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
          </span><span class="pun">},</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
            path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
            component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">CrisisCenterHomeComponent</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">crisisCenterRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CrisisCenterRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>CrisisDetailComponent</code> 不应该再去获取这个危机的详情。 把 <code>CrisisDetailComponent</code> 改成从 <code>ActivatedRoute.data.crisis</code> 属性中获取危机详情，这正是你重新配置路由的恰当时机。 当 <code>CrisisDetailComponent</code> 要求取得危机详情时，它就已经在那里了。</p><p translation-origin="off">The <code>CrisisDetailComponent</code> should no longer fetch the crisis. Update the <code>CrisisDetailComponent</code> to get the crisis from the <code>ActivatedRoute.data.crisis</code> property instead; that's where you said it should be when you re-configured the route. It will be there when the <code>CrisisDetailComponent</code> ask for it.</p><code-example path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts" header="src/app/crisis-center/crisis-detail/crisis-detail.component.ts (ngOnInit v2)" region="ngOnInit" ng-version="9.0.0-rc.11"><div style="display:none">ngOnInit() { this.route.data .subscribe((data: { crisis: Crisis }) =&gt; { this.editName = data.crisis.name; this.crisis = data.crisis; }); }</div><header class="ng-star-inserted">src/app/crisis-center/crisis-detail/crisis-detail.component.ts (ngOnInit v2)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/crisis-center/crisis-detail/crisis-detail.component.ts (ngOnInit v2)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route</span><span class="pun">.</span><span class="pln">data
    </span><span class="pun">.</span><span class="pln">subscribe</span><span class="pun">((</span><span class="pln">data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> crisis</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Crisis</span><span class="pln"> </span><span class="pun">})</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">editName </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">crisis</span><span class="pun">.</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">crisis </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">crisis</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on"><strong>两个关键点</strong></p><p translation-origin="off"><strong>Two critical points</strong></p><ol><li><p translation-result="on">路由器的这个 <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> 接口是可选的。<code>CrisisDetailResolverService</code> 没有继承自某个基类。路由器只要找到了这个方法，就会调用它。</p><p translation-origin="off">The router's <code><a href="api/router/Resolve" class="code-anchor">Resolve</a></code> interface is optional. The <code>CrisisDetailResolverService</code> doesn't inherit from a base class. The router looks for that method and calls it if found.</p></li><li><p translation-result="on">要依赖路由器调用此守卫。不必关心用户用哪种方式导航离开，这是路由器的工作。你只要写出这个类，等路由器从那里取出它就可以了。</p><p translation-origin="off">Rely on the router to call the resolver. Don't worry about all the ways that the user could navigate away. That's the router's job. Write this class and let the router take it from there.</p></li></ol><p translation-result="on">本里程碑中与<em>危机中心</em>有关的代码如下：</p><p translation-origin="off">The relevant <em>Crisis Center</em> code for this milestone follows.</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="app.component.html" path="router/src/app/app.component.html">&lt;h1 class="title"&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/superheroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/admin" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Admin&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/login" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Login&lt;/a&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt; &lt;/nav&gt; &lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> name="popup"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code-pane><code-pane header="crisis-center-home.component.html" path="router/src/app/crisis-center/crisis-center-home/crisis-center-home.component.html">&lt;p&gt;Welcome to the Crisis Center&lt;/p&gt;</code-pane><code-pane header="crisis-center.component.html" path="router/src/app/crisis-center/crisis-center/crisis-center.component.html">&lt;h2&gt;CRISIS CENTER&lt;/h2&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code-pane><code-pane header="crisis-center-routing.module.ts" path="router/src/app/crisis-center/crisis-center-routing.module.4.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CanDeactivateGuard } from '../can-deactivate.guard'; import { CrisisDetailResolverService } from './crisis-detail-resolver.service'; const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent, <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: [CanDeactivateGuard], <a href="api/router/Route#resolve" class="code-anchor">resolve</a>: { crisis: CrisisDetailResolverService } }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(crisisCenterRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class CrisisCenterRoutingModule { }</code-pane><code-pane header="crisis-list.component.html" path="router/src/app/crisis-center/crisis-list/crisis-list.component.html">&lt;ul class="crises"&gt; &lt;li *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let crisis of crises$ | <a href="api/core/testing/async" class="code-anchor">async</a>" [class.selected]="crisis.id === selectedId"&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="[crisis.id]"&gt; &lt;span class="badge"&gt;{{ crisis.id }}&lt;/span&gt;{{ crisis.name }} &lt;/a&gt; &lt;/li&gt; &lt;/ul&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</code-pane><code-pane header="crisis-list.component.ts" path="router/src/app/crisis-center/crisis-list/crisis-list.component.ts">import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a> } from '@angular/core'; import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> } from '@angular/router'; import { CrisisService } from '../crisis.service'; import { Crisis } from '../crisis'; import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-crisis-list', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './crisis-list.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./crisis-list.component.css'] }) export class CrisisListComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { crises$: Observable&lt;Crisis[]&gt;; selectedId: number; constructor( private service: CrisisService, private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> ) {} ngOnInit() { this.crises$ = this.route.paramMap.pipe( switchMap(params =&gt; { this.selectedId = +params.get('id'); return this.service.getCrises(); }) ); } }</code-pane><code-pane header="crisis-detail.component.html" path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.html">&lt;div *<a href="api/common/NgIf" class="code-anchor">ngIf</a>="crisis"&gt; &lt;h3&gt;"{{ editName }}"&lt;/h3&gt; &lt;div&gt; &lt;label&gt;Id: &lt;/label&gt;{{ crisis.id }}&lt;/div&gt; &lt;div&gt; &lt;label&gt;Name: &lt;/label&gt; &lt;input [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="editName" placeholder="name"/&gt; &lt;/div&gt; &lt;p&gt; &lt;button (click)="save()"&gt;Save&lt;/button&gt; &lt;button (click)="cancel()"&gt;Cancel&lt;/button&gt; &lt;/p&gt; &lt;/div&gt;</code-pane><code-pane header="crisis-detail.component.ts" path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts">import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a>, <a href="api/core/HostBinding" class="code-anchor">HostBinding</a> } from '@angular/core'; import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, <a href="api/router/Router" class="code-anchor">Router</a> } from '@angular/router'; import { Observable } from 'rxjs'; import { Crisis } from '../crisis'; import { DialogService } from '../../dialog.service'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-crisis-detail', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './crisis-detail.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./crisis-detail.component.css'] }) export class CrisisDetailComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { crisis: Crisis; editName: string; constructor( private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, private router: <a href="api/router/Router" class="code-anchor">Router</a>, public dialogService: DialogService ) {} ngOnInit() { this.route.data .subscribe((data: { crisis: Crisis }) =&gt; { this.editName = data.crisis.name; this.crisis = data.crisis; }); } cancel() { this.gotoCrises(); } save() { this.crisis.name = this.editName; this.gotoCrises(); } <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>(): Observable&lt;boolean&gt; | boolean { // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged if (!this.crisis || this.crisis.name === this.editName) { return true; } // Otherwise ask the user with the dialog service and return its // observable which resolves to true or false when the user decides return this.dialogService.confirm('Discard <a href="api/core/QueryList#changes" class="code-anchor">changes</a>?'); } gotoCrises() { let crisisId = this.crisis ? this.crisis.id : null; // Pass along the crisis id if available // so that the CrisisListComponent can select that crisis. // Add a totally useless `foo` parameter for kicks. // Relative navigation back to the crises this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { <a href="api/router/NavigationExtras#relativeTo" class="code-anchor">relativeTo</a>: this.route }); } }</code-pane><code-pane header="crisis-detail-resolver.service.ts" path="router/src/app/crisis-center/crisis-detail-resolver.service.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/Resolve" class="code-anchor">Resolve</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a> } from '@angular/router'; import { Observable, of, EMPTY } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; import { CrisisService } from './crisis.service'; import { Crisis } from './crisis'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CrisisDetailResolverService implements <a href="api/router/Resolve" class="code-anchor">Resolve</a>&lt;Crisis&gt; { constructor(private cs: CrisisService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#resolve" class="code-anchor">resolve</a>(route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): Observable&lt;Crisis&gt; | Observable&lt;never&gt; { let id = route.paramMap.get('id'); return this.cs.getCrisis(id).pipe( take(1), mergeMap(crisis =&gt; { if (crisis) { return of(crisis); } else { // id not found this.router.navigate(['/crisis-center']); return EMPTY; } }) ); } }</code-pane><code-pane header="crisis.service.ts" path="router/src/app/crisis-center/crisis.service.ts">import { BehaviorSubject } from 'rxjs'; import { map } from 'rxjs/operators'; import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { MessageService } from '../message.service'; import { Crisis } from './crisis'; import { CRISES } from './mock-crises'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CrisisService { <a href="api/upgrade/static" class="code-anchor">static</a> nextCrisisId = 100; private crises$: BehaviorSubject&lt;Crisis[]&gt; = new BehaviorSubject&lt;Crisis[]&gt;(CRISES); constructor(private messageService: MessageService) { } getCrises() { return this.crises$; } getCrisis(id: number | string) { return this.getCrises().pipe( map(crises =&gt; crises.find(crisis =&gt; crisis.id === +id)) ); } }</code-pane><code-pane header="dialog.service.ts" path="router/src/app/dialog.service.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { Observable, of } from 'rxjs'; /** * Async modal dialog service * DialogService makes this app easier to test by faking this service. * TODO: better modal implementation that doesn't use window.confirm */ @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class DialogService { /** * Ask user to confirm an action. `<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>` explains the action and choices. * Returns observable resolving to `true`=confirm or `false`=cancel */ confirm(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a>?: string): Observable&lt;boolean&gt; { const confirmation = window.confirm(<a href="api/common/http/HttpErrorResponse#message" class="code-anchor">message</a> || 'Is it OK?'); return of(confirmation); }; }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-7-0" tabindex="0" aria-posinset="1" aria-setsize="11" aria-controls="mat-tab-content-7-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-1" tabindex="-1" aria-posinset="2" aria-setsize="11" aria-controls="mat-tab-content-7-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-center-home.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-2" tabindex="-1" aria-posinset="3" aria-setsize="11" aria-controls="mat-tab-content-7-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-center.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-3" tabindex="-1" aria-posinset="4" aria-setsize="11" aria-controls="mat-tab-content-7-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-center-routing.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-4" tabindex="-1" aria-posinset="5" aria-setsize="11" aria-controls="mat-tab-content-7-4" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-list.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-5" tabindex="-1" aria-posinset="6" aria-setsize="11" aria-controls="mat-tab-content-7-5" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-list.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-6" tabindex="-1" aria-posinset="7" aria-setsize="11" aria-controls="mat-tab-content-7-6" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-detail.component.html</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-7" tabindex="-1" aria-posinset="8" aria-setsize="11" aria-controls="mat-tab-content-7-7" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-detail.component.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-8" tabindex="-1" aria-posinset="9" aria-setsize="11" aria-controls="mat-tab-content-7-8" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-detail-resolver.service.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-9" tabindex="-1" aria-posinset="10" aria-setsize="11" aria-controls="mat-tab-content-7-9" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis.service.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-7-10" tabindex="-1" aria-posinset="11" aria-setsize="11" aria-controls="mat-tab-content-7-10" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">dialog.service.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:175px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-38 mat-tab-body-active ng-star-inserted" id="mat-tab-content-7-0" aria-labelledby="mat-tab-label-7-0"><div class="mat-tab-body-content ng-tns-c50-38 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from app.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/superheroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/admin"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Admin</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/login"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Login</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"[{ outlets: { popup: ['compose'] } }]"</span><span class="tag">&gt;</span><span class="pln">Contact</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> [@</span><span class="atn">routeAnimation</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"getAnimationData(routerOutlet)"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> #</span><span class="atn">routerOutlet</span><span class="pun">=</span><span class="atv">"outlet"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"popup"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-39 ng-star-inserted" id="mat-tab-content-7-1" aria-labelledby="mat-tab-label-7-1"><div class="mat-tab-body-content ng-tns-c50-39 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-40 ng-star-inserted" id="mat-tab-content-7-2" aria-labelledby="mat-tab-label-7-2"><div class="mat-tab-body-content ng-tns-c50-40 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-41 ng-star-inserted" id="mat-tab-content-7-3" aria-labelledby="mat-tab-label-7-3"><div class="mat-tab-body-content ng-tns-c50-41 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-42 ng-star-inserted" id="mat-tab-content-7-4" aria-labelledby="mat-tab-label-7-4"><div class="mat-tab-body-content ng-tns-c50-42 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-43 ng-star-inserted" id="mat-tab-content-7-5" aria-labelledby="mat-tab-label-7-5"><div class="mat-tab-body-content ng-tns-c50-43 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-44 ng-star-inserted" id="mat-tab-content-7-6" aria-labelledby="mat-tab-label-7-6"><div class="mat-tab-body-content ng-tns-c50-44 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-45 ng-star-inserted" id="mat-tab-content-7-7" aria-labelledby="mat-tab-label-7-7"><div class="mat-tab-body-content ng-tns-c50-45 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-46 ng-star-inserted" id="mat-tab-content-7-8" aria-labelledby="mat-tab-label-7-8"><div class="mat-tab-body-content ng-tns-c50-46 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-47 ng-star-inserted" id="mat-tab-content-7-9" aria-labelledby="mat-tab-label-7-9"><div class="mat-tab-body-content ng-tns-c50-47 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-48 ng-star-inserted" id="mat-tab-content-7-10" aria-labelledby="mat-tab-label-7-10"><div class="mat-tab-body-content ng-tns-c50-48 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><p translation-result="on">路由守卫</p><p translation-origin="off">Guards</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="auth.guard.ts" path="router/src/app/auth/auth.guard.3.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a> } from '@angular/router'; import { AuthService } from './auth.service'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthGuard implements <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a> { constructor(private authService: AuthService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>( route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { let url: string = state.url; return this.checkLogin(url); } <a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>( route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { return this.canActivate(route, <a href="api/animations/state" class="code-anchor">state</a>); } checkLogin(url: string): boolean { if (this.authService.isLoggedIn) { return true; } // Store the attempted <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> for redirecting this.authService.redirectUrl = url; // Navigate to the login page this.router.navigate(['/login']); return false; } }</code-pane><code-pane header="can-deactivate.guard.ts" path="router/src/app/can-deactivate.guard.ts">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a> } from '@angular/router'; import { Observable } from 'rxjs'; export interface CanComponentDeactivate { <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: () =&gt; Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean; } @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class CanDeactivateGuard implements <a href="api/router/CanDeactivate" class="code-anchor">CanDeactivate</a>&lt;CanComponentDeactivate&gt; { <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>(component: CanComponentDeactivate) { return component.canDeactivate ? component.canDeactivate() : true; } }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-8-0" tabindex="0" aria-posinset="1" aria-setsize="2" aria-controls="mat-tab-content-8-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">auth.guard.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-8-1" tabindex="-1" aria-posinset="2" aria-setsize="2" aria-controls="mat-tab-content-8-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">can-deactivate.guard.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:160px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-49 mat-tab-body-active ng-star-inserted" id="mat-tab-content-8-0" aria-labelledby="mat-tab-label-8-0"><div class="mat-tab-body-content ng-tns-c50-49 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from auth.guard.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln">                           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth.service'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> authService</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">(</span><span class="pln">
    route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> state</span><span class="pun">.</span><span class="pln">url</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><a href="api/router/Route#canActivateChild" class="code-anchor"><span class="pln">canActivateChild</span></a><span class="pun">(</span><span class="pln">
    route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">canActivate</span><span class="pun">(</span><span class="pln">route</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">isLoggedIn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// Store the attempted </span><a href="api/core/SecurityContext#URL" class="code-anchor"><span class="com">URL</span></a><span class="com"> for redirecting</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">redirectUrl </span><span class="pun">=</span><span class="pln"> url</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// Navigate to the login page</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/login'</span><span class="pun">]);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-50 ng-star-inserted" id="mat-tab-content-8-1" aria-labelledby="mat-tab-label-8-1"><div class="mat-tab-body-content ng-tns-c50-50 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><a id="query-parameters"></a> <a id="fragment"></a><h3 id="query-parameters-and-fragments" translation-result="on">查询参数及片段<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#query-parameters-and-fragments"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="query-parameters-and-fragments">Query parameters and fragments<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#query-parameters-and-fragments"><i class="material-icons">link</i></a></h3><p translation-result="on">在这个<a href="guide/router#optional-route-parameters">查询参数</a>例子中，你只为路由指定了参数，但是该如何定义一些所有路由中都可用的可选参数呢？ 这就该“查询参数”登场了。</p><p translation-origin="off">In the <a href="guide/router#optional-route-parameters">route parameters</a> example, you only dealt with parameters specific to the route, but what if you wanted optional parameters available to all routes? This is where query parameters come into play.</p><p translation-result="on"><a href="https://en.wikipedia.org/wiki/Fragment_identifier">片段</a>可以引用页面中带有特定 <code>id</code> 属性的元素.</p><p translation-origin="off"><a href="https://en.wikipedia.org/wiki/Fragment_identifier">Fragments</a> refer to certain elements on the page identified with an <code>id</code> attribute.</p><p translation-result="on">修改 <code>AuthGuard</code> 以提供 <code>session_id</code> 查询参数，在导航到其它路由后，它还会存在。</p><p translation-origin="off">Update the <code>AuthGuard</code> to provide a <code>session_id</code> query that will remain after navigating to another route.</p><p translation-result="on">再添加一个锚点（<code>A</code>）元素，来让你能跳转到页面中的正确位置。</p><p translation-origin="off">Add an <code><a href="api/router/Scroll#anchor" class="code-anchor">anchor</a></code> element so you can jump to a certain point on the page.</p><p translation-result="on">为 <code>router.navigate()</code> 方法添加一个 <code><a href="api/router/NavigationExtras" class="code-anchor">NavigationExtras</a></code> 对象，用来导航到 <code>/login</code> 路由。</p><p translation-origin="off">Add the <code><a href="api/router/NavigationExtras" class="code-anchor">NavigationExtras</a></code> object to the <code>router.navigate()</code> method that navigates you to the <code>/login</code> route.</p><code-example path="router/src/app/auth/auth.guard.4.ts" header="src/app/auth/auth.guard.ts (v3)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/Router" class="code-anchor">Router</a>, <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a>, <a href="api/router/NavigationExtras" class="code-anchor">NavigationExtras</a> } from '@angular/router'; import { AuthService } from './auth.service'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class AuthGuard implements <a href="api/router/CanActivate" class="code-anchor">CanActivate</a>, <a href="api/router/CanActivateChild" class="code-anchor">CanActivateChild</a> { constructor(private authService: AuthService, private router: <a href="api/router/Router" class="code-anchor">Router</a>) {} <a href="api/router/Route#canActivate" class="code-anchor">canActivate</a>(route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { let url: string = state.url; return this.checkLogin(url); } <a href="api/router/Route#canActivateChild" class="code-anchor">canActivateChild</a>(route: <a href="api/router/ActivatedRouteSnapshot" class="code-anchor">ActivatedRouteSnapshot</a>, <a href="api/animations/state" class="code-anchor">state</a>: <a href="api/router/RouterStateSnapshot" class="code-anchor">RouterStateSnapshot</a>): boolean { return this.canActivate(route, <a href="api/animations/state" class="code-anchor">state</a>); } checkLogin(url: string): boolean { if (this.authService.isLoggedIn) { return true; } // Store the attempted <a href="api/core/SecurityContext#URL" class="code-anchor">URL</a> for redirecting this.authService.redirectUrl = url; // Create a dummy session id let sessionId = 123456789; // Set our navigation extras object // that contains our <a href="api/core/global" class="code-anchor">global</a> <a href="api/animations/query" class="code-anchor">query</a> params and fragment let navigationExtras: <a href="api/router/NavigationExtras" class="code-anchor">NavigationExtras</a> = { queryParams: { 'session_id': sessionId }, fragment: '<a href="api/router/Scroll#anchor" class="code-anchor">anchor</a>' }; // Navigate to the login page with extras this.router.navigate(['/login'], navigationExtras); return false; } }</div><header class="ng-star-inserted">src/app/auth/auth.guard.ts (v3)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.guard.ts (v3)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pun">,</span><span class="pln">
  </span><a href="api/router/NavigationExtras" class="code-anchor"><span class="typ">NavigationExtras</span></a><span class="pln">
</span><span class="pun">}</span><span class="pln">                           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth.service'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/CanActivate" class="code-anchor"><span class="typ">CanActivate</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/CanActivateChild" class="code-anchor"><span class="typ">CanActivateChild</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> authService</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AuthService</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  </span><a href="api/router/Route#canActivate" class="code-anchor"><span class="pln">canActivate</span></a><span class="pun">(</span><span class="pln">route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> state</span><span class="pun">.</span><span class="pln">url</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><a href="api/router/Route#canActivateChild" class="code-anchor"><span class="pln">canActivateChild</span></a><span class="pun">(</span><span class="pln">route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRouteSnapshot" class="code-anchor"><span class="typ">ActivatedRouteSnapshot</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/RouterStateSnapshot" class="code-anchor"><span class="typ">RouterStateSnapshot</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">canActivate</span><span class="pun">(</span><span class="pln">route</span><span class="pun">,</span><span class="pln"> </span><a href="api/animations/state" class="code-anchor"><span class="pln">state</span></a><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">isLoggedIn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// Store the attempted </span><a href="api/core/SecurityContext#URL" class="code-anchor"><span class="com">URL</span></a><span class="com"> for redirecting</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">authService</span><span class="pun">.</span><span class="pln">redirectUrl </span><span class="pun">=</span><span class="pln"> url</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// Create a dummy session id</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> sessionId </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123456789</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// Set our navigation extras object</span><span class="pln">
    </span><span class="com">// that contains our </span><a href="api/core/global" class="code-anchor"><span class="com">global</span></a><span class="com"> </span><a href="api/animations/query" class="code-anchor"><span class="com">query</span></a><span class="com"> params and fragment</span><span class="pln">
    </span><span class="kwd">let</span><span class="pln"> navigationExtras</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/NavigationExtras" class="code-anchor"><span class="typ">NavigationExtras</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      queryParams</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">'session_id'</span><span class="pun">:</span><span class="pln"> sessionId </span><span class="pun">},</span><span class="pln">
      fragment</span><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/router/Scroll#anchor" class="code-anchor"><span class="str">anchor</span></a><span class="str">'</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="com">// Navigate to the login page with extras</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/login'</span><span class="pun">],</span><span class="pln"> navigationExtras</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">还可以在导航之间<strong>保留</strong>查询参数和片段，而无需再次在导航中提供。在 <code>LoginComponent</code> 中的 <code>router.navigateUrl()</code> 方法中，添加一个对象作为第二个参数，该<strong>对象</strong>提供了 <code>queryParamsHandling</code> 和 <code>preserveFragment</code>，用于传递当前的查询参数和片段到下一个路由。</p><p translation-origin="off">You can also preserve query parameters and fragments across navigations without having to provide them again when navigating. In the <code>LoginComponent</code>, you'll add an <em>object</em> as the second argument in the <code>router.navigateUrl()</code> function and provide the <code>queryParamsHandling</code> and <code>preserveFragment</code> to pass along the current query parameters and fragment to the next route.</p><code-example path="router/src/app/auth/login/login.component.ts" header="src/app/auth/login/login.component.ts (preserve)" region="preserve" ng-version="9.0.0-rc.11"><div style="display:none">// Set our navigation extras object // that passes on our <a href="api/core/global" class="code-anchor">global</a> <a href="api/animations/query" class="code-anchor">query</a> params and fragment let navigationExtras: <a href="api/router/NavigationExtras" class="code-anchor">NavigationExtras</a> = { queryParamsHandling: 'preserve', preserveFragment: true }; // Redirect the user this.router.navigateByUrl(redirect, navigationExtras);</div><header class="ng-star-inserted">src/app/auth/login/login.component.ts (preserve)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/login/login.component.ts (preserve)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="com">// Set our navigation extras object</span><span class="pln">
</span><span class="com">// that passes on our </span><a href="api/core/global" class="code-anchor"><span class="com">global</span></a><span class="com"> </span><a href="api/animations/query" class="code-anchor"><span class="com">query</span></a><span class="com"> params and fragment</span><span class="pln">
</span><span class="kwd">let</span><span class="pln"> navigationExtras</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/NavigationExtras" class="code-anchor"><span class="typ">NavigationExtras</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  queryParamsHandling</span><span class="pun">:</span><span class="pln"> </span><span class="str">'preserve'</span><span class="pun">,</span><span class="pln">
  preserveFragment</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// Redirect the user</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigateByUrl</span><span class="pun">(</span><span class="pln">redirect</span><span class="pun">,</span><span class="pln"> navigationExtras</span><span class="pun">);</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on"><code>queryParamsHandling</code> 特性还提供了 <code>merge</code> 选项，它将会在导航时保留当前的查询参数，并与其它查询参数合并。</p><p translation-origin="off">The <code>queryParamsHandling</code> feature also provides a <code>merge</code> option, which will preserve and combine the current query parameters with any provided query parameters when navigating.</p></div><p translation-result="on">由于要在登录后导航到<em>危机管理</em>特征区的路由，所以你还得修改它，来处理这些全局查询参数和片段。</p><p translation-origin="off">As you'll be navigating to the <em>Admin Dashboard</em> route after logging in, you'll update it to handle the query parameters and fragment.</p><code-example path="router/src/app/admin/admin-dashboard/admin-dashboard.component.1.ts" header="src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a> } from '@angular/core'; import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> } from '@angular/router'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-admin-dashboard', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './admin-dashboard.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./admin-dashboard.component.css'] }) export class AdminDashboardComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { sessionId: Observable&lt;string&gt;; token: Observable&lt;string&gt;; constructor(private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>) {} ngOnInit() { // Capture the session ID if available this.sessionId = this.route .queryParamMap .pipe(map(params =&gt; params.get('session_id') || 'None')); // Capture the fragment if available this.token = this.route .fragment .pipe(map(fragment =&gt; fragment || 'None')); } }</div><header class="ng-star-inserted">src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Component" class="code-anchor"><span class="typ">Component</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/core/OnInit" class="code-anchor"><span class="typ">OnInit</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">     </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pln"> </span><span class="pun">}</span><span class="pln">         </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> map </span><span class="pun">}</span><span class="pln">                </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Component" class="code-anchor"><span class="lit">Component</span></a><span class="pun">({</span><span class="pln">
  selector</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app-admin-dashboard'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#templateUrl" class="code-anchor"><span class="pln">templateUrl</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'./admin-dashboard.component.html'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#styleUrls" class="code-anchor"><span class="pln">styleUrls</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'./admin-dashboard.component.css'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AdminDashboardComponent</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/core/OnInit" class="code-anchor"><span class="typ">OnInit</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  sessionId</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;string&gt;</span><span class="pun">;</span><span class="pln">
  token</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;string&gt;</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="kwd">private</span><span class="pln"> route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

  ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Capture the session ID if available</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">sessionId </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route
      </span><span class="pun">.</span><span class="pln">queryParamMap
      </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">map</span><span class="pun">(</span><span class="kwd">params</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">params</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'session_id'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="str">'None'</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// Capture the fragment if available</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">token </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route
      </span><span class="pun">.</span><span class="pln">fragment
      </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">map</span><span class="pun">(</span><span class="pln">fragment </span><span class="pun">=&gt;</span><span class="pln"> fragment </span><span class="pun">||</span><span class="pln"> </span><span class="str">'None'</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on"><em>查询参数</em>和<em>片段</em>可通过 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 服务的 <code><a href="api/router/Router#routerState" class="code-anchor">routerState</a></code> 属性使用。和<em>路由参数</em>类似，全局查询参数和片段也是 <code>Observable</code> 对象。 在修改过的<em>英雄管理</em>组件中，你将借助 <code><a href="api/common/AsyncPipe" class="code-anchor">AsyncPipe</a></code> 直接把 <code>Observable</code> 传给模板。</p><p translation-origin="off"><em>Query parameters</em> and <em>fragments</em> are also available through the <code><a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a></code> service. Just like <em>route parameters</em>, the query parameters and fragments are provided as an <code>Observable</code>. The updated <em>Crisis Admin</em> component feeds the <code>Observable</code> directly into the template using the <code><a href="api/common/AsyncPipe" class="code-anchor">AsyncPipe</a></code>.</p><p translation-result="on">按照下列步骤试验下：点击<em>Crisis Admin</em>按钮，它会带着你提供的 <code>queryParamMap</code> 和 <code>fragment</code> 跳转到登录页。 点击登录按钮，你就会被重定向到 <code>Admin Dashboard</code> 页。 注意，它仍然带着上一步提供的 <code>queryParamMap</code> 和 <code>fragment</code>。</p><p translation-origin="off">Now, you can click on the <em>Admin</em> button, which takes you to the <em>Login</em> page with the provided <code>queryParamMap</code> and <code>fragment</code>. After you click the login button, notice that you have been redirected to the <code>Admin Dashboard</code> page with the query parameters and fragment still intact in the address bar.</p><p translation-result="on">你可以用这些持久化信息来携带需要为每个页面都提供的信息，如认证令牌或会话的 ID 等。</p><p translation-origin="off">You can use these persistent bits of information for things that need to be provided across pages like authentication tokens or session ids.</p><div class="alert is-helpful"><p translation-result="on">“查询参数”和“片段”也可以分别用 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 中的 <strong>queryParamsHandling</strong> 和 <strong>preserveFragment</strong> 保存。</p><p translation-origin="off">The <code><a href="api/animations/query" class="code-anchor">query</a> params</code> and <code>fragment</code> can also be preserved using a <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> with the <code>queryParamsHandling</code> and <code>preserveFragment</code> bindings respectively.</p></div><a id="asynchronous-routing"></a><h2 id="milestone-6-asynchronous-routing" translation-result="on">里程碑 6：异步路由<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-6-asynchronous-routing"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="milestone-6-asynchronous-routing">Milestone 6: Asynchronous routing<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#milestone-6-asynchronous-routing"><i class="material-icons">link</i></a></h2><p translation-result="on">完成上面的里程碑后，应用程序很自然地长大了。在继续构建特征区的过程中，应用的尺寸将会变得更大。在某一个时间点，你将达到一个顶点，应用将会需要过多的时间来加载。</p><p translation-origin="off">As you've worked through the milestones, the application has naturally gotten larger. As you continue to build out feature areas, the overall application size will continue to grow. At some point you'll reach a tipping point where the application takes a long time to load.</p><p translation-result="on">如何才能解决这个问题呢？通过引进异步路由，可以获得在请求时才<strong>惰性</strong>加载特性模块的能力。 惰性加载有多个优点：</p><p translation-origin="off">How do you combat this problem? With asynchronous routing, which loads feature modules <em>lazily</em>, on request. Lazy loading has multiple benefits.</p><ul><li><p translation-result="on">你可以只在用户请求时才加载某些特性区。</p><p translation-origin="off">You can load feature areas only when requested by the user.</p></li><li><p translation-result="on">对于那些只访问应用程序某些区域的用户，这样能加快加载速度。</p><p translation-origin="off">You can speed up load time for users that only visit certain areas of the application.</p></li><li><p translation-result="on">你可以持续扩充惰性加载特性区的功能，而不用增加初始加载的包体积。</p><p translation-origin="off">You can continue expanding lazy loaded feature areas without increasing the size of the initial load bundle.</p></li></ul><p translation-result="on">你已经完成了一部分。通过把应用组织成一些模块：<code>AppModule</code>、<code>HeroesModule</code>、<code>AdminModule</code> 和 <code>CrisisCenterModule</code>， 你已经有了可用于实现惰性加载的候选者。</p><p translation-origin="off">You're already part of the way there. By organizing the application into modules—<code>AppModule</code>, <code>HeroesModule</code>, <code>AdminModule</code> and <code>CrisisCenterModule</code>—you have natural candidates for lazy loading.</p><p translation-result="on">有些模块（比如 <code>AppModule</code>）必须在启动时加载，但其它的都可以而且应该惰性加载。 比如 <code>AdminModule</code> 就只有少数已认证的用户才需要它，所以你应该只有在正确的人请求它时才加载。</p><p translation-origin="off">Some modules, like <code>AppModule</code>, must be loaded from the start. But others can and should be lazy loaded. The <code>AdminModule</code>, for example, is needed by a few authorized users, so you should only load it when requested by the right people.</p><a id="lazy-loading-route-config"></a><h3 id="lazy-loading-route-configuration" translation-result="on">惰性加载路由配置<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#lazy-loading-route-configuration"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="lazy-loading-route-configuration">Lazy Loading route configuration<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#lazy-loading-route-configuration"><i class="material-icons">link</i></a></h3><p translation-result="on">把 <code>admin-routing.module.ts</code> 中的 <code>admin</code> 路径从 <code>'admin'</code> 改为空路径 <code>''</code>。</p><p translation-origin="off">Change the <code>admin</code> <strong>path</strong> in the <code>admin-routing.module.ts</code> from <code>'admin'</code> to an empty string, <code>''</code>, the <em>empty path</em>.</p><p translation-result="on"><code><a href="api/router/Router" class="code-anchor">Router</a></code> 支持<em>空路径</em>路由，可以使用它们来分组路由，而不用往 URL 中添加额外的路径片段。 用户仍旧访问 <code>/admin</code>，并且 <code>AdminComponent</code> 仍然作为用来包含子路由的<em>路由组件</em>。</p><p translation-origin="off">The <code><a href="api/router/Router" class="code-anchor">Router</a></code> supports <em>empty path</em> routes; use them to group routes together without adding any additional path segments to the URL. Users will still visit <code>/admin</code> and the <code>AdminComponent</code> still serves as the <em>Routing Component</em> containing child routes.</p><p translation-result="on">打开 <code>AppRoutingModule</code>，并把一个新的 <code>admin</code> 路由添加到它的 <code>appRoutes</code> 数组中。</p><p translation-origin="off">Open the <code>AppRoutingModule</code> and add a new <code>admin</code> route to its <code>appRoutes</code> array.</p><p translation-result="on">给它一个 <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> 属性（替换掉 <code>children</code> 属性）。 <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> 属性接收一个函数，该函数使用浏览器内置的动态导入语法 <code>import('...')</code> 来惰性加载代码，并返回一个承诺（Promise）。 其路径是 <code>AdminModule</code> 的位置（相对于应用的根目录）。 当代码请求并加载完毕后，这个 <code>Promise</code> 就会解析成一个包含 <code><a href="api/core/NgModule" class="code-anchor">NgModule</a></code> 的对象，也就是 <code>AdminModule</code>。</p><p translation-origin="off">Give it a <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> property instead of a <code>children</code> property. The <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> property takes a function that returns a promise using the browser's built-in syntax for lazy loading code using dynamic imports <code>import('...')</code>. The path is the location of the <code>AdminModule</code> (relative to the app root). After the code is requested and loaded, the <code>Promise</code> resolves an object that contains the <code><a href="api/core/NgModule" class="code-anchor">NgModule</a></code>, in this case the <code>AdminModule</code>.</p><code-example path="router/src/app/app-routing.module.5.ts" region="admin-1" header="app-routing.module.ts (load children)" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'admin', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule), },</div><header class="ng-star-inserted">app-routing.module.ts (load children)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from app-routing.module.ts (load children)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln">
  path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/router/Route#loadChildren" class="code-anchor"><span class="pln">loadChildren</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pun">(</span><span class="str">'./admin/admin.module'</span><span class="pun">).</span><span class="kwd">then</span><span class="pun">(</span><span class="pln">m </span><span class="pun">=&gt;</span><span class="pln"> m</span><span class="pun">.</span><span class="typ">AdminModule</span><span class="pun">),</span><span class="pln">
</span><span class="pun">},</span></code>
    </pre></aio-code></code-example><div class="alert is-important"><p translation-result="on"><strong>注意</strong>： 当使用绝对路径时，<code><a href="api/core/NgModule" class="code-anchor">NgModule</a></code> 的文件位置必须以 <code>src/app</code> 开头，以便正确解析。对于自定义的 <a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping">使用绝对路径的路径映射表</a>，项目的 <code>tsconfig.json</code> 中必须配置好 <code>baseUrl</code> 和 <code>paths</code> 属性。</p><p translation-origin="off"><em>Note</em>: When using absolute paths, the <code><a href="api/core/NgModule" class="code-anchor">NgModule</a></code> file location must begin with <code>src/app</code> in order to resolve correctly. For custom <a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping">path mapping with absolute paths</a>, the <code>baseUrl</code> and <code>paths</code> properties in the project <code>tsconfig.json</code> must be configured.</p></div><p translation-result="on">当路由器导航到这个路由时，它会用 <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> 字符串来动态加载 <code>AdminModule</code>，然后把 <code>AdminModule</code> 添加到当前的路由配置中， 最后，它把所请求的路由加载到目标 <code>admin</code> 组件中。</p><p translation-origin="off">When the router navigates to this route, it uses the <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> string to dynamically load the <code>AdminModule</code>. Then it adds the <code>AdminModule</code> routes to its current route configuration. Finally, it loads the requested route to the destination admin component.</p><p translation-result="on">惰性加载和重新配置工作只会发生一次，也就是在该路由<em>首次</em>被请求时。在后续的请求中，该模块和路由都是立即可用的。</p><p translation-origin="off">The lazy loading and re-configuration happen just once, when the route is <em>first</em> requested; the module and routes are available immediately for subsequent requests.</p><div class="alert is-helpful"><p translation-result="on">Angular 提供一个内置模块加载器，支持<strong><code>SystemJS</code></strong>来异步加载模块。如果你使用其它捆绑工具比如 <strong>Webpack</strong>，则使用 Webpack 的机制来异步加载模块。</p><p translation-origin="off">Angular provides a built-in module loader that supports SystemJS to load modules asynchronously. If you were using another bundling tool, such as Webpack, you would use the Webpack mechanism for asynchronously loading modules.</p></div><p translation-result="on">最后一步是把管理特性区从主应用中完全分离开。 根模块 <code>AppModule</code> 既不能加载也不能引用 <code>AdminModule</code> 及其文件。</p><p translation-origin="off">Take the final step and detach the admin feature set from the main application. The root <code>AppModule</code> must neither load nor reference the <code>AdminModule</code> or its files.</p><p translation-result="on">在 <code>app.module.ts</code> 中，从顶部移除 <code>AdminModule</code> 的导入语句，并且从 NgModule 的 <code>imports</code> 数组中移除 <code>AdminModule</code>。</p><p translation-origin="off">In <code>app.module.ts</code>, remove the <code>AdminModule</code> import statement from the top of the file and remove the <code>AdminModule</code> from the NgModule's <code>imports</code> array.</p><a id="can-load-guard"></a><h3 id="canload-guard-guarding-unauthorized-loading-of-feature-modules" translation-result="on"><code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 守卫：保护对特性模块的未授权加载<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canload-guard-guarding-unauthorized-loading-of-feature-modules"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="canload-guard-guarding-unauthorized-loading-of-feature-modules"><em>CanLoad</em> Guard: guarding unauthorized loading of feature modules<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canload-guard-guarding-unauthorized-loading-of-feature-modules"><i class="material-icons">link</i></a></h3><p translation-result="on">你已经使用 <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> 保护 <code>AdminModule</code> 了，它会阻止未授权用户访问管理特性区。如果用户未登录，它就会跳转到登录页。</p><p translation-origin="off">You're already protecting the <code>AdminModule</code> with a <code><a href="api/router/CanActivate" class="code-anchor">CanActivate</a></code> guard that prevents unauthorized users from accessing the admin feature area. It redirects to the login page if the user is not authorized.</p><p translation-result="on">但是路由器仍然会加载 <code>AdminModule</code> —— 即使用户无法访问它的任何一个组件。 理想的方式是，只有在用户已登录的情况下你才加载 <code>AdminModule</code>。</p><p translation-origin="off">But the router is still loading the <code>AdminModule</code> even if the user can't visit any of its components. Ideally, you'd only load the <code>AdminModule</code> if the user is logged in.</p><p translation-result="on">添加一个<strong><code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code></strong>守卫，它只在用户已登录<em>并且</em>尝试访问管理特性区的时候，才加载 <code>AdminModule</code> 一次。</p><p translation-origin="off">Add a <strong><code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code></strong>guard that only loads the <code>AdminModule</code> once the user is logged in <em>and</em> attempts to access the admin feature area.</p><p translation-result="on">现有的 <code>AuthGuard</code> 的 <code>checkLogin()</code> 方法中已经有了支持 <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 守卫的基础逻辑。</p><p translation-origin="off">The existing <code>AuthGuard</code> already has the essential logic in its <code>checkLogin()</code> method to support the <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> guard.</p><p translation-result="on">打开 <code>auth.guard.ts</code>，从 <code>@angular/router</code> 中导入 <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 接口。 把它添加到 <code>AuthGuard</code> 类的 <code>implements</code> 列表中。 然后实现 <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a></code>，代码如下：</p><p translation-origin="off">Open <code>auth.guard.ts</code>. Import the <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> interface from <code>@angular/router</code>. Add it to the <code>AuthGuard</code> class's <code>implements</code> list. Then implement <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>()</code> as follows:</p><code-example path="router/src/app/auth/auth.guard.ts" header="src/app/auth/auth.guard.ts (CanLoad guard)" region="canLoad" ng-version="9.0.0-rc.11"><div style="display:none"><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>(route: <a href="api/router/Route" class="code-anchor">Route</a>): boolean { let url = `/${route.path}`; return this.checkLogin(url); }</div><header class="ng-star-inserted">src/app/auth/auth.guard.ts (CanLoad guard)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/auth/auth.guard.ts (CanLoad guard)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><a href="api/router/Route#canLoad" class="code-anchor"><span class="pln">canLoad</span></a><span class="pun">(</span><span class="pln">route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Route" class="code-anchor"><span class="typ">Route</span></a><span class="pun">):</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">let</span><span class="pln"> url </span><span class="pun">=</span><span class="pln"> </span><span class="str">`/${route.path}`</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">checkLogin</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">路由器会把 <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>()</code> 方法的 <code>route</code> 参数设置为准备访问的目标 URL。 如果用户已经登录了，<code>checkLogin()</code> 方法就会重定向到那个 URL。</p><p translation-origin="off">The router sets the <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>()</code> method's <code>route</code> parameter to the intended destination URL. The <code>checkLogin()</code> method redirects to that URL once the user has logged in.</p><p translation-result="on">现在，把 <code>AuthGuard</code> 导入到 <code>AppRoutingModule</code> 中，并把 <code>AuthGuard</code> 添加到 <code>admin</code> 路由的 <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a></code> 数组中。 完整的 <code>admin</code> 路由是这样的：</p><p translation-origin="off">Now import the <code>AuthGuard</code> into the <code>AppRoutingModule</code> and add the <code>AuthGuard</code> to the <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a></code> array property for the <code>admin</code> route. The completed admin route looks like this:</p><code-example path="router/src/app/app-routing.module.5.ts" region="admin" header="app-routing.module.ts (lazy admin route)" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'admin', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule), <a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>: [AuthGuard] },</div><header class="ng-star-inserted">app-routing.module.ts (lazy admin route)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from app-routing.module.ts (lazy admin route)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln">
  path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/router/Route#loadChildren" class="code-anchor"><span class="pln">loadChildren</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pun">(</span><span class="str">'./admin/admin.module'</span><span class="pun">).</span><span class="kwd">then</span><span class="pun">(</span><span class="pln">m </span><span class="pun">=&gt;</span><span class="pln"> m</span><span class="pun">.</span><span class="typ">AdminModule</span><span class="pun">),</span><span class="pln">
  </span><a href="api/router/Route#canLoad" class="code-anchor"><span class="pln">canLoad</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">AuthGuard</span><span class="pun">]</span><span class="pln">
</span><span class="pun">},</span></code>
    </pre></aio-code></code-example><a id="preloading"></a><h3 id="preloading-background-loading-of-feature-areas" translation-result="on">预加载：特性区的后台加载<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#preloading-background-loading-of-feature-areas"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="preloading-background-loading-of-feature-areas">Preloading: background loading of feature areas<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#preloading-background-loading-of-feature-areas"><i class="material-icons">link</i></a></h3><p translation-result="on">你已经学会了如何按需加载模块，接下来再看看如何使用<em>预加载</em>技术异步加载模块。</p><p translation-origin="off">You've learned how to load modules on-demand. You can also load modules asynchronously with <em>preloading</em>.</p><p translation-result="on">看起来好像应用一直都是这么做的，但其实并非如此。 <code>AppModule</code> 在应用启动时就被加载了，它是<em>立即</em>加载的。 而 <code>AdminModule</code> 只有当用户点击某个链接时才会加载，它是<em>惰性</em>加载的。</p><p translation-origin="off">This may seem like what the app has been doing all along. Not quite. The <code>AppModule</code> is loaded when the application starts; that's <em>eager</em> loading. Now the <code>AdminModule</code> loads only when the user clicks on a link; that's <em>lazy</em> loading.</p><p translation-result="on"><em>预加载</em>是介于两者之间的一种方式。 来看看<em>危机中心</em>。 用户第一眼不会看到它。 默认情况下，<em>英雄管理</em>才是第一视图。 为了获得尽可能小的初始加载体积和最快的加载速度，你应该对 <code>AppModule</code> 和 <code>HeroesModule</code> 进行急性加载。</p><p translation-origin="off"><em>Preloading</em> is something in between. Consider the <em>Crisis Center</em>. It isn't the first view that a user sees. By default, the <em>Heroes</em> are the first view. For the smallest initial payload and fastest launch time, you should eagerly load the <code>AppModule</code> and the <code>HeroesModule</code>.</p><p translation-result="on">你可以惰性加载<em>危机中心</em>。 但是，你几乎可以肯定用户会在启动应用之后的几分钟内访问<em>危机中心</em>。 理想情况下，应用启动时应该只加载 <code>AppModule</code> 和 <code>HeroesModule</code>，然后几乎立即开始后台加载 <code>CrisisCenterModule</code>。 在用户浏览到<em>危机中心</em>之前，该模块应该已经加载完毕，可供访问了。</p><p translation-origin="off">You could lazy load the <em>Crisis Center</em>. But you're almost certain that the user will visit the <em>Crisis Center</em> within minutes of launching the app. Ideally, the app would launch with just the <code>AppModule</code> and the <code>HeroesModule</code> loaded and then, almost immediately, load the <code>CrisisCenterModule</code> in the background. By the time the user navigates to the <em>Crisis Center</em>, its module will have been loaded and ready to go.</p><p translation-result="on">这就是<em>预加载</em>。</p><p translation-origin="off">That's <em>preloading</em>.</p><a id="how-preloading"></a><h4 id="how-preloading-works" translation-result="on">预加载的工作原理<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#how-preloading-works"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="how-preloading-works">How preloading works<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#how-preloading-works"><i class="material-icons">link</i></a></h4><p translation-result="on">在每次<em>成功的</em>导航后，路由器会在自己的配置中查找尚未加载并且可以预加载的模块。 是否加载某个模块，以及要加载哪些模块，取决于<em>预加载策略</em>。</p><p translation-origin="off">After each <em>successful</em> navigation, the router looks in its configuration for an unloaded module that it can preload. Whether it preloads a module, and which modules it preloads, depends upon the <em>preload strategy</em>.</p><p translation-result="on"><code><a href="api/router/Router" class="code-anchor">Router</a></code> 内置了两种预加载策略：</p><p translation-origin="off">The <code><a href="api/router/Router" class="code-anchor">Router</a></code> offers two preloading strategies out of the box:</p><ul><li><p translation-result="on">完全不预加载，这是默认值。惰性加载的特性区仍然会按需加载。</p><p translation-origin="off">No preloading at all which is the default. Lazy loaded feature areas are still loaded on demand.</p></li><li><p translation-result="on">预加载所有惰性加载的特性区。</p><p translation-origin="off">Preloading of all lazy loaded feature areas.</p></li></ul><p translation-result="on">默认情况下，路由器或者完全不预加载或者预加载每个惰性加载模块。 路由器还支持<a href="guide/router#custom-preloading">自定义预加载策略</a>，以便完全控制要预加载哪些模块以及何时加载。</p><p translation-origin="off">Out of the box, the router either never preloads, or preloads every lazy load module. The <code><a href="api/router/Router" class="code-anchor">Router</a></code> also supports <a href="guide/router#custom-preloading">custom preloading strategies</a> for fine control over which modules to preload and when.</p><p translation-result="on">在下一节，你将会把 <code>CrisisCenterModule</code> 改为默认惰性加载的，并使用 <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> 策略来尽快加载它（以及<em>所有其它</em>惰性加载模块）。</p><p translation-origin="off">In this next section, you'll update the <code>CrisisCenterModule</code> to load lazily by default and use the <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> strategy to load it (and <em>all other</em> lazy loaded modules) as soon as possible.</p><a id="lazy-load-crisis-center"></a><h4 id="lazy-load-the-crisis-center" translation-result="on">惰性加载<em>危机中心</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#lazy-load-the-crisis-center"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="lazy-load-the-crisis-center">Lazy load the <em>crisis center</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#lazy-load-the-crisis-center"><i class="material-icons">link</i></a></h4><p translation-result="on">修改路由配置，来惰性加载 <code>CrisisCenterModule</code>。修改的步骤和配置惰性加载 <code>AdminModule</code> 时一样。</p><p translation-origin="off">Update the route configuration to lazy load the <code>CrisisCenterModule</code>. Take the same steps you used to configure <code>AdminModule</code> for lazy load.</p><ol><li><p translation-result="on">把 <code>CrisisCenterRoutingModule</code> 中的路径从 <code>crisis-center</code> 改为空字符串。</p><p translation-origin="off">Change the <code>crisis-center</code> path in the <code>CrisisCenterRoutingModule</code> to an empty string.</p></li><li><p translation-result="on">往 <code>AppRoutingModule</code> 中添加一个 <code>crisis-center</code> 路由。</p><p translation-origin="off">Add a <code>crisis-center</code> route to the <code>AppRoutingModule</code>.</p></li><li><p translation-result="on">设置 <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> 字符串来加载 <code>CrisisCenterModule</code>。</p><p translation-origin="off">Set the <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> string to load the <code>CrisisCenterModule</code>.</p></li><li><p translation-result="on">从 <code>app.module.ts</code> 中移除所有对 <code>CrisisCenterModule</code> 的引用。</p><p translation-origin="off">Remove all mention of the <code>CrisisCenterModule</code> from <code>app.module.ts</code>.</p></li></ol><p translation-result="on">下面是打开预加载之前的模块修改版：</p><p translation-origin="off">Here are the updated modules <em>before enabling preload</em>:</p><code-tabs ng-version="9.0.0-rc.11"><div style="display:none"><code-pane header="app.module.ts" path="router/src/app/app.module.ts" region="preload">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations'; import { <a href="api/router/Router" class="code-anchor">Router</a> } from '@angular/router'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { AppRoutingModule } from './app-routing.module'; import { HeroesModule } from './heroes/heroes.module'; import { AuthModule } from './auth/auth.module'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor">BrowserAnimationsModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, HeroesModule, AuthModule, AppRoutingModule, ], declarations: [ AppComponent, ComposeMessageComponent, PageNotFoundComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }</code-pane><code-pane header="app-routing.module.ts" path="router/src/app/app-routing.module.6.ts" region="preload-v1">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a>, } from '@angular/router'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { AuthGuard } from './auth/auth.guard'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'compose', component: ComposeMessageComponent, outlet: 'popup' }, { path: 'admin', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule), <a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>: [AuthGuard] }, { path: 'crisis-center', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./crisis-center/crisis-center.module').then(m =&gt; m.CrisisCenterModule) }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/heroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule {}</code-pane><code-pane header="crisis-center-routing.module.ts" path="router/src/app/crisis-center/crisis-center-routing.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CanDeactivateGuard } from '../can-deactivate.guard'; import { CrisisDetailResolverService } from './crisis-detail-resolver.service'; const crisisCenterRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: '', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent, <a href="api/router/Route#canDeactivate" class="code-anchor">canDeactivate</a>: [CanDeactivateGuard], <a href="api/router/Route#resolve" class="code-anchor">resolve</a>: { crisis: CrisisDetailResolverService } }, { path: '', component: CrisisCenterHomeComponent } ] } ] } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(crisisCenterRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class CrisisCenterRoutingModule { }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="mat-tab-group code-tab-group mat-primary"><mat-tab-header class="mat-tab-header"><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div role="tablist" class="mat-tab-list" style="transform:translateX(0)"><div class="mat-tab-labels"><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label mat-tab-label-active ng-star-inserted" id="mat-tab-label-9-0" tabindex="0" aria-posinset="1" aria-setsize="3" aria-controls="mat-tab-content-9-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-9-1" tabindex="-1" aria-posinset="2" aria-setsize="3" aria-controls="mat-tab-content-9-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app-routing.module.ts</span></div></div><div role="tab" mattablabelwrapper="" mat-ripple="" cdkmonitorelementfocus="" class="mat-ripple mat-tab-label ng-star-inserted" id="mat-tab-label-9-2" tabindex="-1" aria-posinset="3" aria-setsize="3" aria-controls="mat-tab-content-9-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">crisis-center-routing.module.ts</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:160px"></mat-ink-bar></div></div><div aria-hidden="true" mat-ripple="" class="mat-ripple mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4 mat-tab-header-pagination-disabled"><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-51 mat-tab-body-active ng-star-inserted" id="mat-tab-content-9-0" aria-labelledby="mat-tab-label-9-0"><div class="mat-tab-body-content ng-tns-c50-51 ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from app.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser/animations'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./compose-message/compose-message.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">        </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app-routing.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroesModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">            </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./heroes/heroes.module'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthModule</span><span class="pln"> </span><span class="pun">}</span><span class="pln">              </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth/auth.module'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/platform-browser/animations/BrowserAnimationsModule" class="code-anchor"><span class="typ">BrowserAnimationsModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">HeroesModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AuthModule</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AppRoutingModule</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">ComposeMessageComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-52 ng-star-inserted" id="mat-tab-content-9-1" aria-labelledby="mat-tab-label-9-1"><div class="mat-tab-body-content ng-tns-c50-52 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c50-53 ng-star-inserted" id="mat-tab-content-9-2" aria-labelledby="mat-tab-label-9-2"><div class="mat-tab-body-content ng-tns-c50-53 ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs><p translation-result="on">你可以现在尝试它，并确认在点击了“Crisis Center”按钮之后加载了 <code>CrisisCenterModule</code>。</p><p translation-origin="off">You could try this now and confirm that the <code>CrisisCenterModule</code> loads after you click the "Crisis Center" button.</p><p translation-result="on">要为所有惰性加载模块启用预加载功能，请从 Angular 的路由模块中导入 <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code>。</p><p translation-origin="off">To enable preloading of all lazy loaded modules, import the <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> token from the Angular router package.</p><p translation-result="on"><code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 方法的第二个参数接受一个附加配置选项对象。 <code><a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor">preloadingStrategy</a></code> 就是其中之一。 把 <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> 添加到 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">forRoot()</a></code> 调用中：</p><p translation-origin="off">The second argument in the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> method takes an object for additional configuration options. The <code><a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor">preloadingStrategy</a></code> is one of those options. Add the <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> token to the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">forRoot()</a></code> call:</p><code-example path="router/src/app/app-routing.module.6.ts" header="src/app/app-routing.module.ts (preload all)" region="forRoot" ng-version="9.0.0-rc.11"><div style="display:none">RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: true, // &lt;-- debugging purposes only <a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor">preloadingStrategy</a>: <a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a> } )</div><header class="ng-star-inserted">src/app/app-routing.module.ts (preload all)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (preload all)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
  appRoutes</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
    </span><a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor"><span class="pln">preloadingStrategy</span></a><span class="pun">:</span><span class="pln"> </span><a href="api/router/PreloadAllModules" class="code-anchor"><span class="typ">PreloadAllModules</span></a><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">)</span></code>
    </pre></aio-code></code-example><p translation-result="on">这会让 <code><a href="api/router/Router" class="code-anchor">Router</a></code> 预加载器立即加载<em>所有</em>惰性加载路由（带 <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> 属性的路由）。</p><p translation-origin="off">This tells the <code><a href="api/router/Router" class="code-anchor">Router</a></code> preloader to immediately load <em>all</em> lazy loaded routes (routes with a <code><a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a></code> property).</p><p translation-result="on">当访问 <code>http://localhost:4200</code> 时，<code>/heroes</code> 路由立即随之启动，并且路由器在加载了 <code>HeroesModule</code> 之后立即开始加载 <code>CrisisCenterModule</code>。</p><p translation-origin="off">When you visit <code>http://localhost:4200</code>, the <code>/heroes</code> route loads immediately upon launch and the router starts loading the <code>CrisisCenterModule</code> right after the <code>HeroesModule</code> loads.</p><p translation-result="on">意外的是，<code>AdminModule</code><em>没有</em>预加载，有什么东西阻塞了它。</p><p translation-origin="off">Surprisingly, the <code>AdminModule</code> does <em>not</em> preload. Something is blocking it.</p><a id="preload-canload"></a><h4 id="canload-blocks-preload" translation-result="on">CanLoad 会阻塞预加载<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canload-blocks-preload"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="canload-blocks-preload">CanLoad blocks preload<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#canload-blocks-preload"><i class="material-icons">link</i></a></h4><p translation-result="on"><code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> 策略不会加载被<a href="guide/router#can-load-guard">CanLoad</a>守卫所保护的特性区。这是刻意设计的。</p><p translation-origin="off">The <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> strategy does not load feature areas protected by a <a href="guide/router#can-load-guard">CanLoad</a> guard. This is by design.</p><p translation-result="on">你几步之前刚刚给 <code>AdminModule</code> 中的路由添加了 <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 守卫，以阻塞加载那个模块，直到用户认证结束。 <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> 守卫的优先级高于预加载策略。</p><p translation-origin="off">You added a <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> guard to the route in the <code>AdminModule</code> a few steps back to block loading of that module until the user is authorized. That <code><a href="api/router/CanLoad" class="code-anchor">CanLoad</a></code> guard takes precedence over the preload strategy.</p><p translation-result="on">如果你要加载一个模块<em>并且</em>保护它防止未授权访问，请移除 <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a></code> 守卫，只单独依赖<a href="guide/router#can-activate-guard">CanActivate</a>守卫。</p><p translation-origin="off">If you want to preload a module <em>and</em> guard against unauthorized access, drop the <code><a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>()</code> guard method and rely on the <a href="guide/router#can-activate-guard">canActivate()</a> guard alone.</p><a id="custom-preloading"></a><h3 id="custom-preloading-strategy" translation-result="on">自定义预加载策略<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#custom-preloading-strategy"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="custom-preloading-strategy">Custom Preloading Strategy<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#custom-preloading-strategy"><i class="material-icons">link</i></a></h3><p translation-result="on">在大多数场景下，预加载每个惰性加载模块就很好了，但是有时候它却并不是正确的选择，特别是在移动设备和低带宽连接下。 你可能出于用户的测量和其它商业和技术因素而选择只对某些特性模块进行预加载。</p><p translation-origin="off">Preloading every lazy loaded modules works well in many situations, but it isn't always the right choice, especially on mobile devices and over low bandwidth connections. You may choose to preload only certain feature modules, based on user metrics and other business and technical factors.</p><p translation-result="on">使用自定义预加载策略，你可以控制路由器预加载哪些路由以及如何加载。</p><p translation-origin="off">You can control what and how the router preloads with a custom preloading strategy.</p><p translation-result="on">在这一节，你将添加一个自定义策略，它<em>只</em>预加载那些 <code>data.preload</code> 标志为 <code>true</code> 的路由。 回忆一下，你可以往路由的 <code>data</code> 属性中添加任何东西。</p><p translation-origin="off">In this section, you'll add a custom strategy that <em>only</em> preloads routes whose <code>data.preload</code> flag is set to <code>true</code>. Recall that you can add anything to the <code>data</code> property of a route.</p><p translation-result="on">在 <code>AppRoutingModule</code> 的 <code>crisis-center</code> 路由中设置 <code>data.preload</code> 标志。</p><p translation-origin="off">Set the <code>data.preload</code> flag in the <code>crisis-center</code> route in the <code>AppRoutingModule</code>.</p><code-example path="router/src/app/app-routing.module.ts" header="src/app/app-routing.module.ts (route data preload)" region="preload-v2" ng-version="9.0.0-rc.11"><div style="display:none">{ path: 'crisis-center', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./crisis-center/crisis-center.module').then(m =&gt; m.CrisisCenterModule), data: { preload: true } },</div><header class="ng-star-inserted">src/app/app-routing.module.ts (route data preload)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (route data preload)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{</span><span class="pln">
  path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/router/Route#loadChildren" class="code-anchor"><span class="pln">loadChildren</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pun">(</span><span class="str">'./crisis-center/crisis-center.module'</span><span class="pun">).</span><span class="kwd">then</span><span class="pun">(</span><span class="pln">m </span><span class="pun">=&gt;</span><span class="pln"> m</span><span class="pun">.</span><span class="typ">CrisisCenterModule</span><span class="pun">),</span><span class="pln">
  data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> preload</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">},</span></code>
    </pre></aio-code></code-example><p translation-result="on">生成一个新的 <code>SelectivePreloadingStrategy</code> 服务。</p><p translation-origin="off">Generate a new <code>SelectivePreloadingStrategy</code> service.</p><code-example language="none" class="code-shell" ng-version="9.0.0-rc.11"><div style="display:none">ng generate service selective-preloading-strategy</div><aio-code><pre class="lang-none prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate service selective</span><span class="pun">-</span><span class="pln">preloading</span><span class="pun">-</span><span class="pln">strategy</span></code>
    </pre></aio-code></code-example><code-example path="router/src/app/selective-preloading-strategy.service.ts" header="src/app/selective-preloading-strategy.service.ts (excerpt)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Injectable" class="code-anchor">Injectable</a> } from '@angular/core'; import { <a href="api/router/PreloadingStrategy" class="code-anchor">PreloadingStrategy</a>, <a href="api/router/Route" class="code-anchor">Route</a> } from '@angular/router'; import { Observable, of } from 'rxjs'; @<a href="api/core/Injectable" class="code-anchor">Injectable</a>({ <a href="api/core/Injectable#providedIn" class="code-anchor">providedIn</a>: 'root', }) export class SelectivePreloadingStrategyService implements <a href="api/router/PreloadingStrategy" class="code-anchor">PreloadingStrategy</a> { preloadedModules: string[] = []; preload(route: <a href="api/router/Route" class="code-anchor">Route</a>, load: () =&gt; Observable&lt;any&gt;): Observable&lt;any&gt; { if (route.data &amp;&amp; route.data['preload']) { // add the route path to the preloaded module array this.preloadedModules.push(route.path); // <a href="api/animations/browser/testing/MockAnimationDriver#log" class="code-anchor">log</a> the route path to the console console.log('Preloaded: ' + route.path); return load(); } else { return of(null); } } }</div><header class="ng-star-inserted">src/app/selective-preloading-strategy.service.ts (excerpt)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/selective-preloading-strategy.service.ts (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Injectable" class="code-anchor"><span class="typ">Injectable</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/PreloadingStrategy" class="code-anchor"><span class="typ">PreloadingStrategy</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route" class="code-anchor"><span class="typ">Route</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pun">,</span><span class="pln"> of </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Injectable" class="code-anchor"><span class="lit">Injectable</span></a><span class="pun">({</span><span class="pln">
  </span><a href="api/core/Injectable#providedIn" class="code-anchor"><span class="pln">providedIn</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'root'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SelectivePreloadingStrategyService</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/router/PreloadingStrategy" class="code-anchor"><span class="typ">PreloadingStrategy</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  preloadedModules</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">

  preload</span><span class="pun">(</span><span class="pln">route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Route" class="code-anchor"><span class="typ">Route</span></a><span class="pun">,</span><span class="pln"> load</span><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;any&gt;</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;any&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">route</span><span class="pun">.</span><span class="pln">data </span><span class="pun">&amp;&amp;</span><span class="pln"> route</span><span class="pun">.</span><span class="pln">data</span><span class="pun">[</span><span class="str">'preload'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// add the route path to the preloaded module array</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">preloadedModules</span><span class="pun">.</span><span class="pln">push</span><span class="pun">(</span><span class="pln">route</span><span class="pun">.</span><span class="pln">path</span><span class="pun">);</span><span class="pln">

      </span><span class="com">// </span><a href="api/animations/browser/testing/MockAnimationDriver#log" class="code-anchor"><span class="com">log</span></a><span class="com"> the route path to the console</span><span class="pln">
      console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Preloaded: '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> route</span><span class="pun">.</span><span class="pln">path</span><span class="pun">);</span><span class="pln">

      </span><span class="kwd">return</span><span class="pln"> load</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> of</span><span class="pun">(</span><span class="kwd">null</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>SelectivePreloadingStrategyService</code> 实现了 <code><a href="api/router/PreloadingStrategy" class="code-anchor">PreloadingStrategy</a></code>，它只有一个方法 <code>preload</code>。</p><p translation-origin="off"><code>SelectivePreloadingStrategyService</code> implements the <code><a href="api/router/PreloadingStrategy" class="code-anchor">PreloadingStrategy</a></code>, which has one method, <code>preload</code>.</p><p translation-result="on">路由器会用两个参数调用调用 <code>preload</code> 方法：</p><p translation-origin="off">The router calls the <code>preload</code> method with two arguments:</p><ol><li><p translation-result="on">要加载的路由。</p><p translation-origin="off">The route to consider.</p></li><li><p translation-result="on">一个加载器（loader）函数，它能异步加载带路由的模块。</p><p translation-origin="off">A loader function that can load the routed module asynchronously.</p></li></ol><p translation-result="on"><code>preload</code> 的实现必须返回一个 <code>Observable</code>。 如果该路由应该预加载，它就会返回调用加载器函数所返回的 <code>Observable</code>。 如果该路由<em>不</em>应该预加载，它就返回一个 <code>null</code> 值的 <code>Observable</code> 对象。</p><p translation-origin="off">An implementation of <code>preload</code> must return an <code>Observable</code>. If the route should preload, it returns the observable returned by calling the loader function. If the route should <em>not</em> preload, it returns an <code>Observable</code> of <code>null</code>.</p><p translation-result="on">在这个例子中，<code>preload</code> 方法只有在路由的 <code>data.preload</code> 标识为真时才会加载该路由。</p><p translation-origin="off">In this sample, the <code>preload</code> method loads the route if the route's <code>data.preload</code> flag is truthy.</p><p translation-result="on">它还有一个副作用。 <code>SelectivePreloadingStrategyService</code> 会把所选路由的 <code>path</code> 记录在它的公共数组 <code>preloadedModules</code> 中。</p><p translation-origin="off">It also has a side-effect. <code>SelectivePreloadingStrategyService</code> logs the <code>path</code> of a selected route in its public <code>preloadedModules</code> array.</p><p translation-result="on">很快，你就会扩展 <code>AdminDashboardComponent</code> 来注入该服务，并且显示它的 <code>preloadedModules</code> 数组。</p><p translation-origin="off">Shortly, you'll extend the <code>AdminDashboardComponent</code> to inject this service and display its <code>preloadedModules</code> array.</p><p translation-result="on">但是首先，要对 <code>AppRoutingModule</code> 做少量修改。</p><p translation-origin="off">But first, make a few changes to the <code>AppRoutingModule</code>.</p><ol><li><p translation-result="on">把 <code>SelectivePreloadingStrategyService</code> 导入到 <code>AppRoutingModule</code> 中。</p><p translation-origin="off">Import <code>SelectivePreloadingStrategyService</code> into <code>AppRoutingModule</code>.</p></li><li><p translation-result="on">把 <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> 策略替换成对 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">forRoot()</a></code> 的调用，并且传入这个 <code>SelectivePreloadingStrategyService</code>。</p><p translation-origin="off">Replace the <code><a href="api/router/PreloadAllModules" class="code-anchor">PreloadAllModules</a></code> strategy in the call to <code><a href="api/router/RouterModule#forRoot" class="code-anchor">forRoot()</a></code> with this <code>SelectivePreloadingStrategyService</code>.</p></li><li><p translation-result="on">把 <code>SelectivePreloadingStrategyService</code> 策略添加到 <code>AppRoutingModule</code> 的 <code>providers</code> 数组中，以便它可以注入到应用中的任何地方。</p><p translation-origin="off">Add the <code>SelectivePreloadingStrategyService</code> strategy to the <code>AppRoutingModule</code> providers array so it can be injected elsewhere in the app.</p></li></ol><p translation-result="on">现在，编辑 <code>AdminDashboardComponent</code> 以显示这些预加载路由的日志。</p><p translation-origin="off">Now edit the <code>AdminDashboardComponent</code> to display the log of preloaded routes.</p><ol><li><p translation-result="on">导入 <code>SelectivePreloadingStrategyService</code>（它是一个服务）。</p><p translation-origin="off">Import the <code>SelectivePreloadingStrategyService</code>.</p></li><li><p translation-result="on">把它注入到仪表盘的构造函数中。</p><p translation-origin="off">Inject it into the dashboard's constructor.</p></li><li><p translation-result="on">修改模板来显示这个策略服务的 <code>preloadedModules</code> 数组。</p><p translation-origin="off">Update the template to display the strategy service's <code>preloadedModules</code> array.</p></li></ol><p translation-result="on">当完成时，代码如下：</p><p translation-origin="off">When you're done it looks like this.</p><code-example path="router/src/app/admin/admin-dashboard/admin-dashboard.component.ts" header="src/app/admin/admin-dashboard/admin-dashboard.component.ts (preloaded modules)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/Component" class="code-anchor">Component</a>, <a href="api/core/OnInit" class="code-anchor">OnInit</a> } from '@angular/core'; import { <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a> } from '@angular/router'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { SelectivePreloadingStrategyService } from '../../selective-preloading-strategy.service'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-admin-dashboard', <a href="api/core/Component#templateUrl" class="code-anchor">templateUrl</a>: './admin-dashboard.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./admin-dashboard.component.css'] }) export class AdminDashboardComponent implements <a href="api/core/OnInit" class="code-anchor">OnInit</a> { sessionId: Observable&lt;string&gt;; token: Observable&lt;string&gt;; modules: string[]; constructor( private route: <a href="api/router/ActivatedRoute" class="code-anchor">ActivatedRoute</a>, preloadStrategy: SelectivePreloadingStrategyService ) { this.modules = preloadStrategy.preloadedModules; } ngOnInit() { // Capture the session ID if available this.sessionId = this.route .queryParamMap .pipe(map(params =&gt; params.get('session_id') || 'None')); // Capture the fragment if available this.token = this.route .fragment .pipe(map(fragment =&gt; fragment || 'None')); } }</div><header class="ng-star-inserted">src/app/admin/admin-dashboard/admin-dashboard.component.ts (preloaded modules)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/admin/admin-dashboard/admin-dashboard.component.ts (preloaded modules)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Component" class="code-anchor"><span class="typ">Component</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/core/OnInit" class="code-anchor"><span class="typ">OnInit</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">       </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Observable</span><span class="pln"> </span><span class="pun">}</span><span class="pln">           </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> map </span><span class="pun">}</span><span class="pln">                  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'rxjs/operators'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">SelectivePreloadingStrategyService</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../../selective-preloading-strategy.service'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Component" class="code-anchor"><span class="lit">Component</span></a><span class="pun">({</span><span class="pln">
  selector</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app-admin-dashboard'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#templateUrl" class="code-anchor"><span class="pln">templateUrl</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'./admin-dashboard.component.html'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#styleUrls" class="code-anchor"><span class="pln">styleUrls</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'./admin-dashboard.component.css'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AdminDashboardComponent</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><a href="api/core/OnInit" class="code-anchor"><span class="typ">OnInit</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
  sessionId</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;string&gt;</span><span class="pun">;</span><span class="pln">
  token</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Observable</span><span class="str">&lt;string&gt;</span><span class="pun">;</span><span class="pln">
  modules</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">[];</span><span class="pln">

  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> route</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/ActivatedRoute" class="code-anchor"><span class="typ">ActivatedRoute</span></a><span class="pun">,</span><span class="pln">
    preloadStrategy</span><span class="pun">:</span><span class="pln"> </span><span class="typ">SelectivePreloadingStrategyService</span><span class="pln">
  </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">modules </span><span class="pun">=</span><span class="pln"> preloadStrategy</span><span class="pun">.</span><span class="pln">preloadedModules</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  ngOnInit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Capture the session ID if available</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">sessionId </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route
      </span><span class="pun">.</span><span class="pln">queryParamMap
      </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">map</span><span class="pun">(</span><span class="kwd">params</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">params</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'session_id'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="str">'None'</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// Capture the fragment if available</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">token </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">route
      </span><span class="pun">.</span><span class="pln">fragment
      </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">map</span><span class="pun">(</span><span class="pln">fragment </span><span class="pun">=&gt;</span><span class="pln"> fragment </span><span class="pun">||</span><span class="pln"> </span><span class="str">'None'</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">一旦应用加载完了初始路由，<code>CrisisCenterModule</code> 也被预加载了。 通过 <code>Admin</code> 特性区中的记录就可以验证它，“Preloaded Modules”中列出了 <code>crisis-center</code>。 它也被记录到了浏览器的控制台。</p><p translation-origin="off">Once the application loads the initial route, the <code>CrisisCenterModule</code> is preloaded. Verify this by logging in to the <code>Admin</code> feature area and noting that the <code>crisis-center</code> is listed in the <code>Preloaded Modules</code>. It's also logged to the browser's console.</p><a id="redirect-advanced"></a><h2 id="migrating-urls-with-redirects" translation-result="on">使用重定向迁移 URL<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#migrating-urls-with-redirects"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="migrating-urls-with-redirects">Migrating URLs with Redirects<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#migrating-urls-with-redirects"><i class="material-icons">link</i></a></h2><p translation-result="on">你已经设置好了路由，并且用命令式和声明式的方式导航到了很多不同的路由。但是，任何应用的需求都会随着时间而改变。 你把链接 <code>/heroes</code> 和 <code>hero/:id</code> 指向了 <code>HeroListComponent</code> 和 <code>HeroDetailComponent</code> 组件。 如果有这样一个需求，要把链接 <code>heroes</code> 变成 <code>superheroes</code>，你仍然希望以前的 URL 能正常导航。 但你也不想在应用中找到并修改每一个链接，这时候，重定向就可以省去这些琐碎的重构工作。</p><p translation-origin="off">You've setup the routes for navigating around your application. You've used navigation imperatively and declaratively to many different routes. But like any application, requirements change over time. You've setup links and navigation to <code>/heroes</code> and <code>/hero/:id</code> from the <code>HeroListComponent</code> and <code>HeroDetailComponent</code> components. If there was a requirement that links to <code>heroes</code> become <code>superheroes</code>, you still want the previous URLs to navigate correctly. You also don't want to go and update every link in your application, so redirects makes refactoring routes trivial.</p><a id="url-refactor"></a><h3 id="changing-heroes-to-superheroes" translation-result="on">把 <code>/heroes</code> 修改为 <code>/superheros</code><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#changing-heroes-to-superheroes"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="changing-heroes-to-superheroes">Changing /heroes to /superheroes<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#changing-heroes-to-superheroes"><i class="material-icons">link</i></a></h3><p translation-result="on">先取得 <code>Hero</code> 路由，并把它们迁移到新的 URL。<code><a href="api/router/Router" class="code-anchor">Router</a></code>（路由器）会在开始导航之前先在配置中检查所有重定向语句，以便将来按需触发重定向。要支持这种修改，你就要在 <code>heroes-routing.module</code> 文件中把老的路由重定向到新的路由。</p><p translation-origin="off">Let's take the <code>Hero</code> routes and migrate them to new URLs. The <code><a href="api/router/Router" class="code-anchor">Router</a></code> checks for redirects in your configuration before navigating, so each redirect is triggered when needed. To support this change, you'll add redirects from the old routes to the new routes in the <code>heroes-routing.module</code>.</p><code-example path="router/src/app/heroes/heroes-routing.module.ts" header="src/app/heroes/heroes-routing.module.ts (heroes redirects)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { HeroListComponent } from './hero-list/hero-list.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; const heroesRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'heroes', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/superheroes' }, { path: 'hero/:id', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/superhero/:id' }, { path: 'superheroes', component: HeroListComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'heroes' } }, { path: 'superhero/:id', component: HeroDetailComponent, data: { <a href="api/animations/animation" class="code-anchor">animation</a>: 'hero' } } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forChild(heroesRoutes) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class HeroesRoutingModule { }</div><header class="ng-star-inserted">src/app/heroes/heroes-routing.module.ts (heroes redirects)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/heroes-routing.module.ts (heroes redirects)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-list/hero-list.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-detail/hero-detail.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> heroesRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/superheroes'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'hero/:id'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/superhero/:id'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'superheroes'</span><span class="pun">,</span><span class="pln">  component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroListComponent</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/animations/animation" class="code-anchor"><span class="pln">animation</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'heroes'</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'superhero/:id'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HeroDetailComponent</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/animations/animation" class="code-anchor"><span class="pln">animation</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forChild</span><span class="pun">(</span><span class="pln">heroesRoutes</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroesRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">注意，这里有两种类型的重定向。第一种是不带参数的从 <code>/heroes</code> 重定向到 <code>/superheroes</code>。这是一种非常直观的重定向。第二种是从 <code>/hero/:id</code> 重定向到 <code>/superhero/:id</code>，它还要包含一个 <code>:id</code> 路由参数。 路由器重定向时使用强大的模式匹配功能，这样，路由器就会检查 URL，并且把 <code>path</code> 中带的路由参数替换成相应的目标形式。以前，你导航到形如 <code>/hero/15</code> 的 URL 时，带了一个路由参数 <code>id</code>，它的值是 <code>15</code>。</p><p translation-origin="off">You'll notice two different types of redirects. The first change is from <code>/heroes</code> to <code>/superheroes</code> without any parameters. This is a straightforward redirect, unlike the change from <code>/hero/:id</code> to <code>/superhero/:id</code>, which includes the <code>:id</code> route parameter. Router redirects also use powerful pattern matching, so the <code><a href="api/router/Router" class="code-anchor">Router</a></code> inspects the URL and replaces route parameters in the <code>path</code> with their appropriate destination. Previously, you navigated to a URL such as <code>/hero/15</code> with a route parameter <code>id</code> of <code>15</code>.</p><div class="alert is-helpful"><p translation-result="on">在重定向的时候，路由器还支持<a href="guide/router#query-parameters">查询参数</a>和<a href="guide/router#fragment">片段(fragment)</a>。</p><p translation-origin="off">The <code><a href="api/router/Router" class="code-anchor">Router</a></code> also supports <a href="guide/router#query-parameters">query parameters</a> and the <a href="guide/router#fragment">fragment</a> when using redirects.</p><ul><li><p translation-result="on">当使用绝对地址重定向时，路由器将会使用路由配置的 <code><a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a></code> 属性中规定的查询参数和片段。</p><p translation-origin="off">When using absolute redirects, the <code><a href="api/router/Router" class="code-anchor">Router</a></code> will use the query parameters and the fragment from the redirectTo in the route config.</p></li><li><p translation-result="on">当使用相对地址重定向时，路由器将会使用源地址（跳转前的地址）中的查询参数和片段。</p><p translation-origin="off">When using relative redirects, the <code><a href="api/router/Router" class="code-anchor">Router</a></code> use the query params and the fragment from the source URL.</p></li></ul></div><p translation-result="on">在修改 <code>app-routing.module.ts</code> 之前，你要先考虑一条重要的规则。 目前，你把空路径路由重定向到了 <code>/heroes</code>，它又被重定向到了 <code>/superheroes</code>。这样<em>不行</em>，从设计上就不行。 因为路由器在每一层的路由配置中只会处理一次重定向。这样可以防止出现无限循环的重定向。</p><p translation-origin="off">Before updating the <code>app-routing.module.ts</code>, you'll need to consider an important rule. Currently, our empty path route redirects to <code>/heroes</code>, which redirects to <code>/superheroes</code>. This <em>won't</em> work and is by design as the <code><a href="api/router/Router" class="code-anchor">Router</a></code> handles redirects once at each level of routing configuration. This prevents chaining of redirects, which can lead to endless redirect loops.</p><p translation-result="on">所以，你要在 <code>app-routing.module.ts</code> 中修改空路径路由，让它重定向到 <code>/superheroes</code>。</p><p translation-origin="off">So instead, you'll update the empty path route in <code>app-routing.module.ts</code> to redirect to <code>/superheroes</code>.</p><code-example path="router/src/app/app-routing.module.ts" header="src/app/app-routing.module.ts (superheroes redirect)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/router/RouterModule" class="code-anchor">RouterModule</a>, <a href="api/router/Routes" class="code-anchor">Routes</a> } from '@angular/router'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { AuthGuard } from './auth/auth.guard'; import { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service'; const appRoutes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ { path: 'compose', component: ComposeMessageComponent, outlet: 'popup' }, { path: 'admin', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule), <a href="api/router/Route#canLoad" class="code-anchor">canLoad</a>: [AuthGuard] }, { path: 'crisis-center', <a href="api/router/Route#loadChildren" class="code-anchor">loadChildren</a>: () =&gt; import('./crisis-center/crisis-center.module').then(m =&gt; m.CrisisCenterModule), data: { preload: true } }, { path: '', <a href="api/router/Route#redirectTo" class="code-anchor">redirectTo</a>: '/superheroes', <a href="api/router/Route#pathMatch" class="code-anchor">pathMatch</a>: '<a href="api/core/Version#full" class="code-anchor">full</a>' }, { path: '**', component: PageNotFoundComponent } ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ RouterModule.forRoot( appRoutes, { <a href="api/router/ExtraOptions#enableTracing" class="code-anchor">enableTracing</a>: false, // &lt;-- debugging purposes only <a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor">preloadingStrategy</a>: SelectivePreloadingStrategyService, } ) ], exports: [ <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> ] }) export class AppRoutingModule { }</div><header class="ng-star-inserted">src/app/app-routing.module.ts (superheroes redirect)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app-routing.module.ts (superheroes redirect)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./compose-message/compose-message.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AuthGuard</span><span class="pln"> </span><span class="pun">}</span><span class="pln">                          </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./auth/auth.guard'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">SelectivePreloadingStrategyService</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./selective-preloading-strategy.service'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> appRoutes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'compose'</span><span class="pun">,</span><span class="pln">
    component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ComposeMessageComponent</span><span class="pun">,</span><span class="pln">
    outlet</span><span class="pun">:</span><span class="pln"> </span><span class="str">'popup'</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#loadChildren" class="code-anchor"><span class="pln">loadChildren</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pun">(</span><span class="str">'./admin/admin.module'</span><span class="pun">).</span><span class="kwd">then</span><span class="pun">(</span><span class="pln">m </span><span class="pun">=&gt;</span><span class="pln"> m</span><span class="pun">.</span><span class="typ">AdminModule</span><span class="pun">),</span><span class="pln">
    </span><a href="api/router/Route#canLoad" class="code-anchor"><span class="pln">canLoad</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">AuthGuard</span><span class="pun">]</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'crisis-center'</span><span class="pun">,</span><span class="pln">
    </span><a href="api/router/Route#loadChildren" class="code-anchor"><span class="pln">loadChildren</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pun">(</span><span class="str">'./crisis-center/crisis-center.module'</span><span class="pun">).</span><span class="kwd">then</span><span class="pun">(</span><span class="pln">m </span><span class="pun">=&gt;</span><span class="pln"> m</span><span class="pun">.</span><span class="typ">CrisisCenterModule</span><span class="pun">),</span><span class="pln">
    data</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> preload</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">   </span><a href="api/router/Route#redirectTo" class="code-anchor"><span class="pln">redirectTo</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'/superheroes'</span><span class="pun">,</span><span class="pln"> </span><a href="api/router/Route#pathMatch" class="code-anchor"><span class="pln">pathMatch</span></a><span class="pun">:</span><span class="pln"> </span><span class="str">'</span><a href="api/core/Version#full" class="code-anchor"><span class="str">full</span></a><span class="str">'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">{</span><span class="pln"> path</span><span class="pun">:</span><span class="pln"> </span><span class="str">'**'</span><span class="pun">,</span><span class="pln"> component</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">
      appRoutes</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
        </span><a href="api/router/ExtraOptions#enableTracing" class="code-anchor"><span class="pln">enableTracing</span></a><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="com">// &lt;-- debugging purposes only</span><span class="pln">
        </span><a href="api/router/ExtraOptions#preloadingStrategy" class="code-anchor"><span class="pln">preloadingStrategy</span></a><span class="pun">:</span><span class="pln"> </span><span class="typ">SelectivePreloadingStrategyService</span><span class="pun">,</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  exports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln">
  </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppRoutingModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">由于 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令没有关联到路由配置，所以你需要修改相关的路由链接，以便在新的路由激活时，它们也能保持激活状态。你要修改 <code>app.component.ts</code> 模板中的 <code>/heroes</code> 路由链接。</p><p translation-origin="off"><code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>s aren't tied to route configuration, so you'll need to update the associated router links so they remain active when the new route is active. You'll update the <code>app.component.ts</code> template for the <code>/heroes</code> routerLink.</p><code-example path="router/src/app/app.component.html" header="src/app/app.component.html (superheroes active routerLink)" ng-version="9.0.0-rc.11"><div style="display:none">&lt;h1 class="title"&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/crisis-center" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Crisis Center&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/superheroes" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Heroes&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/admin" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Admin&lt;/a&gt; &lt;a <a href="api/router/RouterLink" class="code-anchor">routerLink</a>="/login" <a href="api/router/RouterLinkActive" class="code-anchor">routerLinkActive</a>="active"&gt;Login&lt;/a&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt; &lt;/nav&gt; &lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> #routerOutlet="outlet"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; &lt;/div&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a> name="popup"&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;</div><header class="ng-star-inserted">src/app/app.component.html (superheroes active routerLink)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.html (superheroes active routerLink)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;h1</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">Angular </span><a href="api/router/Router" class="code-anchor"><span class="pln">Router</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;nav&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/crisis-center"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/superheroes"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/admin"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Admin</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> </span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pun">=</span><span class="atv">"/login"</span><span class="pln"> </span><a href="api/router/RouterLinkActive" class="code-anchor"><span class="atn">routerLinkActive</span></a><span class="pun">=</span><span class="atv">"active"</span><span class="tag">&gt;</span><span class="pln">Login</span><span class="tag">&lt;/a&gt;</span><span class="pln">
  </span><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"[{ outlets: { popup: ['compose'] } }]"</span><span class="tag">&gt;</span><span class="pln">Contact</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> [@</span><span class="atn">routeAnimation</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"getAnimationData(routerOutlet)"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> #</span><span class="atn">routerOutlet</span><span class="pun">=</span><span class="atv">"outlet"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"popup"</span><span class="tag">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="tag">router-outlet</span></a><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">修改 <code>hero-detail.component.ts</code> 中的 <code>goToHeroes()</code> 方法，使用可选的路由参数导航回 <code>/superheroes</code>。</p><p translation-origin="off">Update the <code>goToHeroes()</code> method in the <code>hero-detail.component.ts</code> to navigate back to <code>/superheroes</code> with the optional route parameters.</p><code-example path="router/src/app/heroes/hero-detail/hero-detail.component.ts" region="redirect" header="src/app/heroes/hero-detail/hero-detail.component.ts (goToHeroes)" ng-version="9.0.0-rc.11"><div style="display:none">gotoHeroes(hero: Hero) { let heroId = hero ? hero.id : null; // Pass along the hero id if available // so that the HeroList component can select that hero. // Include a junk 'foo' property for fun. this.router.navigate(['/superheroes', { id: heroId, foo: 'foo' }]); }</div><header class="ng-star-inserted">src/app/heroes/hero-detail/hero-detail.component.ts (goToHeroes)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-detail/hero-detail.component.ts (goToHeroes)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">gotoHeroes</span><span class="pun">(</span><span class="pln">hero</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">let</span><span class="pln"> heroId </span><span class="pun">=</span><span class="pln"> hero </span><span class="pun">?</span><span class="pln"> hero</span><span class="pun">.</span><span class="pln">id </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
  </span><span class="com">// Pass along the hero id if available</span><span class="pln">
  </span><span class="com">// so that the HeroList component can select that hero.</span><span class="pln">
  </span><span class="com">// Include a junk 'foo' property for fun.</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">router</span><span class="pun">.</span><span class="pln">navigate</span><span class="pun">([</span><span class="str">'/superheroes'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> heroId</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">:</span><span class="pln"> </span><span class="str">'foo'</span><span class="pln"> </span><span class="pun">}]);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">当这些重定向设置好之后，所有以前的路由都指向了它们的新目标，并且每个 URL 也仍然能正常工作。</p><p translation-origin="off">With the redirects setup, all previous routes now point to their new destinations and both URLs still function as intended.</p><a id="inspect-config"></a><h2 id="inspect-the-routers-configuration" translation-result="on">审查路由器配置<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#inspect-the-routers-configuration"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="inspect-the-routers-configuration">Inspect the router's configuration<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#inspect-the-routers-configuration"><i class="material-icons">link</i></a></h2><p translation-result="on">你把大量的精力投入到在一系列路由模块文件里配置路由器上，并且小心的<a href="guide/router#routing-module-order">以合适的顺序</a>列出它们。 这些路由是否真的如同你预想的那样执行了？ 路由器的真实配置是怎样的？</p><p translation-origin="off">You put a lot of effort into configuring the router in several routing module files and were careful to list them <a href="guide/router#routing-module-order">in the proper order</a>. Are routes actually evaluated as you planned? How is the router really configured?</p><p translation-result="on">通过注入它（Router）并检查它的 <code><a href="api/router/Router#config" class="code-anchor">config</a></code> 属性，你可以随时审查路由器的当前配置。 例如，把 <code>AppModule</code> 修改为这样，并在浏览器的控制台窗口中查看最终的路由配置。</p><p translation-origin="off">You can inspect the router's current configuration any time by injecting it and examining its <code><a href="api/router/Router#config" class="code-anchor">config</a></code> property. For example, update the <code>AppModule</code> as follows and look in the browser console window to see the finished route configuration.</p><code-example path="router/src/app/app.module.7.ts" header="src/app/app.module.ts (inspect the router config)" region="inspect-config" ng-version="9.0.0-rc.11"><div style="display:none">export class AppModule { // Diagnostic only: inspect router configuration constructor(router: <a href="api/router/Router" class="code-anchor">Router</a>) { // Use a custom replacer to display function names in the route configs const replacer = (key, value) =&gt; (typeof value === 'function') ? value.name : value; console.log('<a href="api/router/Routes" class="code-anchor">Routes</a>: ', JSON.stringify(router.config, replacer, 2)); } }</div><header class="ng-star-inserted">src/app/app.module.ts (inspect the router config)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (inspect the router config)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// Diagnostic only: inspect router configuration</span><span class="pln">
  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">router</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Router" class="code-anchor"><span class="typ">Router</span></a><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Use a custom replacer to display function names in the route configs</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> replacer </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span class="pln"> </span><span class="kwd">value</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">.</span><span class="pln">name </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">;</span><span class="pln">

    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'</span><a href="api/router/Routes" class="code-anchor"><span class="str">Routes</span></a><span class="str">: '</span><span class="pun">,</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">stringify</span><span class="pun">(</span><span class="pln">router</span><span class="pun">.</span><span class="pln">config</span><span class="pun">,</span><span class="pln"> replacer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><a id="final-app"></a><h2 id="wrap-up-and-final-app" translation-result="on">总结与最终的应用<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#wrap-up-and-final-app"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="wrap-up-and-final-app">Wrap up and final app<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#wrap-up-and-final-app"><i class="material-icons">link</i></a></h2><p translation-result="on">本章中涉及到了很多背景知识，而且本应用程序也太大了，所以没法在这里显示。请访问<live-example title="Router Sample in Stackblitz" ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="Router Sample in Stackblitz" href="generated/live-examples/router/stackblitz.html">Router Sample in Stackblitz</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>，在那里你可以下载最终的源码。</p><p translation-origin="off">You've covered a lot of ground in this guide and the application is too big to reprint here. Please visit the<live-example title="Router Sample in Stackblitz" ng-version="9.0.0-rc.11"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" title="Router Sample in Stackblitz" href="generated/live-examples/router/stackblitz.html">Router Sample in Stackblitz</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/router/router.zip">下载范例</a></span></span></span></live-example>where you can download the final source code.</p><a id="appendices"></a><h2 id="appendices" translation-result="on">附录<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendices"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="appendices">Appendices<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendices"><i class="material-icons">link</i></a></h2><p translation-result="on">本章剩下的部分是一组附录，它详尽阐述了那些曾匆匆带过的知识点。</p><p translation-origin="off">The balance of this guide is a set of appendices that elaborate some of the points you covered quickly above.</p><p translation-result="on">该附件中的内容不是必须的，感兴趣的人才需要阅读它。</p><p translation-origin="off">The appendix material isn't essential. Continued reading is for the curious.</p><a id="link-parameters-array"></a><h3 id="appendix-link-parameters-array" translation-result="on">附录：链接参数数组<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendix-link-parameters-array"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="appendix-link-parameters-array">Appendix: link parameters array<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendix-link-parameters-array"><i class="material-icons">link</i></a></h3><p translation-result="on">链接参数数组保存路由导航时所需的成分：</p><p translation-origin="off">A link parameters array holds the following ingredients for router navigation:</p><ul><li><p translation-result="on">指向目标组件的那个路由的<em>路径（path）</em></p><p translation-origin="off">The <em>path</em> of the route to the destination component.</p></li><li><p translation-result="on">必备路由参数和可选路由参数，它们将进入该路由的 URL</p><p translation-origin="off">Required and optional route parameters that go into the route URL.</p></li></ul><p translation-result="on">你可以把 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> 指令绑定到一个数组，就像这样：</p><p translation-origin="off">You can bind the <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> directive to such an array like this:</p><code-example path="router/src/app/app.component.3.ts" header="src/app/app.component.ts (h-anchor)" region="h-anchor" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/heroes']"&gt;Heroes&lt;/a&gt;</div><header class="ng-star-inserted">src/app/app.component.ts (h-anchor)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (h-anchor)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/heroes']"</span><span class="tag">&gt;</span><span class="pln">Heroes</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">在指定路由参数时，你写过一个双元素的数组，就像这样：</p><p translation-origin="off">You've written a two element array when specifying a route parameter like this:</p><code-example path="router/src/app/heroes/hero-list/hero-list.component.1.html" header="src/app/heroes/hero-list/hero-list.component.html (nav-to-detail)" region="nav-to-detail" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/hero', hero.id]"&gt; &lt;span class="badge"&gt;{{ hero.id }}&lt;/span&gt;{{ hero.name }} &lt;/a&gt;</div><header class="ng-star-inserted">src/app/heroes/hero-list/hero-list.component.html (nav-to-detail)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/heroes/hero-list/hero-list.component.html (nav-to-detail)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/hero', hero.id]"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"badge"</span><span class="tag">&gt;</span><span class="pln">{{ hero.id }}</span><span class="tag">&lt;/span&gt;</span><span class="pln">{{ hero.name }}
</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">你可以在对象中提供可选的路由参数，就像这样：</p><p translation-origin="off">You can provide optional route parameters in an object like this:</p><code-example path="router/src/app/app.component.3.ts" header="src/app/app.component.ts (cc-query-params)" region="cc-query-params" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center', { foo: 'foo' }]"&gt;Crisis Center&lt;/a&gt;</div><header class="ng-star-inserted">src/app/app.component.ts (cc-query-params)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (cc-query-params)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/crisis-center', { foo: 'foo' }]"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">这三个例子涵盖了你在单级路由的应用中所需的一切。在你添加一个像<em>危机中心</em>一样的子路由时，你可以创建新链接数组。</p><p translation-origin="off">These three examples cover the need for an app with one level routing. The moment you add a child router, such as the crisis center, you create new link array possibilities.</p><p translation-result="on">回忆一下，你曾为<em>危机中心</em>指定过一个默认的子路由，以便能使用这种简单的 <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code>。</p><p translation-origin="off">Recall that you specified a default child route for the crisis center so this simple <code><a href="api/router/RouterLink" class="code-anchor">RouterLink</a></code> is fine.</p><code-example path="router/src/app/app.component.3.ts" header="src/app/app.component.ts (cc-anchor-w-default)" region="cc-anchor-w-default" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center']"&gt;Crisis Center&lt;/a&gt;</div><header class="ng-star-inserted">src/app/app.component.ts (cc-anchor-w-default)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (cc-anchor-w-default)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/crisis-center']"</span><span class="tag">&gt;</span><span class="pln">Crisis Center</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">分解一下。</p><p translation-origin="off">Parse it out.</p><ul><li><p translation-result="on">数组中的第一个条目标记出了父路由(<code>/crisis-center</code>)。</p><p translation-origin="off">The first item in the array identifies the parent route (<code>/crisis-center</code>).</p></li><li><p translation-result="on">这个父路由没有参数，因此这步已经完成了。</p><p translation-origin="off">There are no parameters for this parent route so you're done with it.</p></li><li><p translation-result="on">没有默认的子路由，因此你得选取一个。</p><p translation-origin="off">There is no default for the child route so you need to pick one.</p></li><li><p translation-result="on">你决定跳转到 <code>CrisisListComponent</code>，它的路由路径是'/'，但你不用显式的添加它。</p><p translation-origin="off">You're navigating to the <code>CrisisListComponent</code>, whose route path is <code>/</code>, but you don't need to explicitly add the slash.</p></li><li><p translation-result="on">哇！<code>['/crisis-center']</code>。</p><p translation-origin="off">Voilà! <code>['/crisis-center']</code>.</p></li></ul><p translation-result="on">更进一步。这次要构建一个从根组件往下导航到“巨龙危机”时的链接参数数组：</p><p translation-origin="off">Take it a step further. Consider the following router link that navigates from the root of the application down to the <em>Dragon Crisis</em>:</p><code-example path="router/src/app/app.component.3.ts" header="src/app/app.component.ts (Dragon-anchor)" region="Dragon-anchor" ng-version="9.0.0-rc.11"><div style="display:none">&lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center', 1]"&gt;Dragon Crisis&lt;/a&gt;</div><header class="ng-star-inserted">src/app/app.component.ts (Dragon-anchor)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (Dragon-anchor)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;a</span><span class="pln"> [</span><a href="api/router/RouterLink" class="code-anchor"><span class="atn">routerLink</span></a><span class="pln">]</span><span class="pun">=</span><span class="atv">"['/crisis-center', 1]"</span><span class="tag">&gt;</span><span class="pln">Dragon Crisis</span><span class="tag">&lt;/a&gt;</span></code>
    </pre></aio-code></code-example><ul><li><p translation-result="on">数组中的第一个条目标记出了父路由(<code>/crisis-center</code>)。</p><p translation-origin="off">The first item in the array identifies the parent route (<code>/crisis-center</code>).</p></li><li><p translation-result="on">这个父路由没有参数，因此这步已经完成了。</p><p translation-origin="off">There are no parameters for this parent route so you're done with it.</p></li><li><p translation-result="on">数组中的第二个条目（'/:id'）用来标记出到指定危机的详情页的子路由。</p><p translation-origin="off">The second item identifies the child route details about a particular crisis (<code>/:id</code>).</p></li><li><p translation-result="on">详细的子路由需要一个 <code>id</code> 路由参数。</p><p translation-origin="off">The details child route requires an <code>id</code> route parameter.</p></li><li><p translation-result="on">你把<em>巨龙危机</em>的 <code>id</code> 添加为该数组中的第二个条目（<code>1</code>）。</p><p translation-origin="off">You added the <code>id</code> of the <em>Dragon Crisis</em> as the second item in the array (<code>1</code>).</p></li><li><p translation-result="on">最终生成的路径是 <code>/crisis-center/1</code>。</p><p translation-origin="off">The resulting path is <code>/crisis-center/1</code>.</p></li></ul><p translation-result="on">只要想，你也可以用<em>危机中心</em>路由单独重定义 <code>AppComponent</code> 的模板：</p><p translation-origin="off">If you wanted to, you could redefine the <code>AppComponent</code> template with <em>Crisis Center</em> routes exclusively:</p><code-example path="router/src/app/app.component.3.ts" header="src/app/app.component.ts (template)" region="template" ng-version="9.0.0-rc.11"><div style="display:none">template: ` &lt;h1 class="title"&gt;Angular <a href="api/router/Router" class="code-anchor">Router</a>&lt;/h1&gt; &lt;nav&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center']"&gt;Crisis Center&lt;/a&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center/1', { foo: 'foo' }]"&gt;Dragon Crisis&lt;/a&gt; &lt;a [<a href="api/router/RouterLink" class="code-anchor">routerLink</a>]="['/crisis-center/2']"&gt;Shark Crisis&lt;/a&gt; &lt;/nav&gt; &lt;<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt;&lt;/<a href="api/router/RouterOutlet" class="code-anchor">router-outlet</a>&gt; `</div><header class="ng-star-inserted">src/app/app.component.ts (template)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.component.ts (template)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">template</span><span class="pun">:</span><span class="pln"> </span><span class="str">`
  &lt;h1 class="title"&gt;Angular </span><a href="api/router/Router" class="code-anchor"><span class="str">Router</span></a><span class="str">&lt;/h1&gt;
  &lt;nav&gt;
    &lt;a [</span><a href="api/router/RouterLink" class="code-anchor"><span class="str">routerLink</span></a><span class="str">]="['/crisis-center']"&gt;Crisis Center&lt;/a&gt;
    &lt;a [</span><a href="api/router/RouterLink" class="code-anchor"><span class="str">routerLink</span></a><span class="str">]="['/crisis-center/1', { foo: 'foo' }]"&gt;Dragon Crisis&lt;/a&gt;
    &lt;a [</span><a href="api/router/RouterLink" class="code-anchor"><span class="str">routerLink</span></a><span class="str">]="['/crisis-center/2']"&gt;Shark Crisis&lt;/a&gt;
  &lt;/nav&gt;
  &lt;</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="str">router-outlet</span></a><span class="str">&gt;&lt;/</span><a href="api/router/RouterOutlet" class="code-anchor"><span class="str">router-outlet</span></a><span class="str">&gt;
`</span></code>
    </pre></aio-code></code-example><p translation-result="on">总结：你可以用一级、两级或多级路由来写应用程序。 链接参数数组提供了用来表示任意深度路由的链接参数数组以及任意合法的路由参数序列、必须的路由器参数以及可选的路由参数对象。</p><p translation-origin="off">In sum, you can write applications with one, two or more levels of routing. The link parameters array affords the flexibility to represent any routing depth and any legal sequence of route paths, (required) router parameters, and (optional) route parameter objects.</p><a id="browser-url-styles"></a> <a id="location-strategy"></a><h3 id="appendix-locationstrategy-and-browser-url-styles" translation-result="on">附录：<em>LocationStrategy</em> 以及浏览器 URL 样式<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendix-locationstrategy-and-browser-url-styles"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="appendix-locationstrategy-and-browser-url-styles">Appendix: <em>LocationStrategy</em> and browser URL styles<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#appendix-locationstrategy-and-browser-url-styles"><i class="material-icons">link</i></a></h3><p translation-result="on">当路由器导航到一个新的组件视图时，它会用该视图的 URL 来更新浏览器的当前地址以及历史。 严格来说，这个 URL 其实是本地的，浏览器不会把该 URL 发给服务器，并且不会重新加载此页面。</p><p translation-origin="off">When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. This is a strictly local URL. The browser shouldn't send this URL to the server and should not reload the page.</p><p translation-result="on">现代 HTML 5 浏览器支持<a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries">history.pushState</a> API， 这是一项可以改变浏览器的当前地址和历史，却又不会触发服务端页面请求的技术。 路由器可以合成出一个“自然的”URL，它看起来和那些需要进行页面加载的 URL 没什么区别。</p><p translation-origin="off">Modern HTML5 browsers support <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries" title="HTML5 browser history push-state">history.pushState</a>, a technique that changes a browser's location and history without triggering a server page request. The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load.</p><p translation-result="on">下面是<em>危机中心</em>的 URL 在“HTML 5 pushState”风格下的样子：</p><p translation-origin="off">Here's the <em>Crisis Center</em> URL in this "HTML5 pushState" style:</p><code-example format="nocode" ng-version="9.0.0-rc.11"><div style="display:none">localhost:3002/crisis-center/</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">3002</span><span class="pun">/</span><span class="pln">crisis</span><span class="pun">-</span><span class="pln">center</span><span class="pun">/</span></code>
    </pre></aio-code></code-example><p translation-result="on">老旧的浏览器在当前地址的 URL 变化时总会往服务器发送页面请求……唯一的例外规则是：当这些变化位于“#”（被称为“hash”）后面时不会发送。通过把应用内的路由 URL 拼接在 <code>#</code> 之后，路由器可以获得这条“例外规则”带来的优点。下面是到<em>危机中心</em>路由的“hash URL”：</p><p translation-origin="off">Older browsers send page requests to the server when the location URL changes <em>unless</em> the change occurs after a "#" (called the "hash"). Routers can take advantage of this exception by composing in-application route URLs with hashes. Here's a "hash URL" that routes to the <em>Crisis Center</em>.</p><code-example format="nocode" ng-version="9.0.0-rc.11"><div style="display:none">localhost:3002/src/#/crisis-center/</div><aio-code><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">localhost</span><span class="pun">:</span><span class="lit">3002</span><span class="pun">/</span><span class="pln">src</span><span class="pun">/</span><span class="com">#/crisis-center/</span></code>
    </pre></aio-code></code-example><p translation-result="on">路由器通过两种 <code><a href="api/common/LocationStrategy" class="code-anchor">LocationStrategy</a></code> 提供者来支持所有这些风格：</p><p translation-origin="off">The router supports both styles with two <code><a href="api/common/LocationStrategy" class="code-anchor">LocationStrategy</a></code> providers:</p><ol><li><p translation-result="on"><code><a href="api/common/PathLocationStrategy" class="code-anchor">PathLocationStrategy</a></code> - 默认的策略，支持“HTML 5 pushState”风格。</p><p translation-origin="off"><code><a href="api/common/PathLocationStrategy" class="code-anchor">PathLocationStrategy</a></code>—the default "HTML5 pushState" style.</p></li><li><p translation-result="on"><code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code> - 支持“hash URL”风格。</p><p translation-origin="off"><code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code>—the "hash URL" style.</p></li></ol><p translation-result="on"><code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 函数把 <code><a href="api/common/LocationStrategy" class="code-anchor">LocationStrategy</a></code> 设置成了 <code><a href="api/common/PathLocationStrategy" class="code-anchor">PathLocationStrategy</a></code>，使其成为了默认策略。 你可以在启动过程中改写（override）它，来切换到 <code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code> 风格 —— 如果你更喜欢这种。</p><p translation-origin="off">The <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> function sets the <code><a href="api/common/LocationStrategy" class="code-anchor">LocationStrategy</a></code> to the <code><a href="api/common/PathLocationStrategy" class="code-anchor">PathLocationStrategy</a></code>, making it the default strategy. You can switch to the <code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code> with an override during the bootstrapping process if you prefer it.</p><div class="alert is-helpful"><p translation-result="on">要学习关于“提供者”和启动过程的更多知识，参见<a href="guide/dependency-injection#bootstrap">依赖注入</a>一章。</p><p translation-origin="off">Learn about providers and the bootstrap process in the <a href="guide/dependency-injection#bootstrap">Dependency Injection guide</a>.</p></div><h4 id="which-strategy-is-best" translation-result="on">哪种策略更好？<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#which-strategy-is-best"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="which-strategy-is-best">Which strategy is best?<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#which-strategy-is-best"><i class="material-icons">link</i></a></h4><p translation-result="on">你必须选择一种策略，并且在项目的早期就这么干。一旦该应用进入了生产阶段，要改起来可就不容易了，因为外面已经有了大量对应用 URL 的引用。</p><p translation-origin="off">You must choose a strategy and you need to make the right call early in the project. It won't be easy to change later once the application is in production and there are lots of application URL references in the wild.</p><p translation-result="on">几乎所有的 Angular 项目都会使用默认的 HTML 5 风格。它生成的 URL 更易于被用户理解，它也为将来做<strong>服务端渲染</strong>预留了空间。</p><p translation-origin="off">Almost all Angular projects should use the default HTML5 style. It produces URLs that are easier for users to understand. And it preserves the option to do <em>server-side rendering</em> later.</p><p translation-result="on">在服务器端渲染指定的页面，是一项可以在该应用首次加载时大幅提升响应速度的技术。那些原本需要十秒甚至更长时间加载的应用，可以预先在服务端渲染好，并在少于一秒的时间内完整呈现在用户的设备上。</p><p translation-origin="off">Rendering critical pages on the server is a technique that can greatly improve perceived responsiveness when the app first loads. An app that would otherwise take ten or more seconds to start could be rendered on the server and delivered to the user's device in less than a second.</p><p translation-result="on">只有当应用的 URL 看起来像是标准的 Web URL，中间没有 hash（#）时，这个选项才能生效。</p><p translation-origin="off">This option is only available if application URLs look like normal web URLs without hashes (#) in the middle.</p><p translation-result="on">除非你有强烈的理由不得不使用 hash 路由，否则就应该坚决使用默认的 HTML 5 路由风格。</p><p translation-origin="off">Stick with the default unless you have a compelling reason to resort to hash routes.</p><h4 id="the-base-href" translation-result="on"><em>&lt;base href&gt;</em> 标签<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-base-href"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="the-base-href">The <em>&lt;base href&gt;</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#the-base-href"><i class="material-icons">link</i></a></h4><p translation-result="on">路由器使用浏览器的 <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries" title="HTML5 browser history push-state">history.pushState</a> API 进行导航。借助 <code>pushState</code> 你可以让应用中的 URL 路径看上去就像你期望的那样，比如 <code>localhost:4200/crisis-center</code>，应用内的 URL 和服务器的 URL 没有区别。</p><p translation-origin="off">The router uses the browser's <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries" title="HTML5 browser history push-state">history.pushState</a> for navigation. Thanks to <code>pushState</code>, you can make in-app URL paths look the way you want them to look, e.g. <code>localhost:4200/crisis-center</code>. The in-app URLs can be indistinguishable from server URLs.</p><p translation-result="on">现代的 HTML5 浏览器都支持 <code>pushState</code>，这也就是为什么很多人把这种 URL 形式称为 "HTML 5" 风格的 URL。</p><p translation-origin="off">Modern HTML5 browsers were the first to support <code>pushState</code> which is why many people refer to these URLs as "HTML5 style" URLs.</p><div class="alert is-helpful"><p translation-result="on">路由器默认使用 HTML5 风格的导航。 在附录中的 <a href="guide/router#browser-url-styles">LocationStrategy 与浏览器 URL 风格</a>中，你可以了解为何推荐使用 HTML5 风格的 URL，如何调整其行为，以及必要时如何切换到老式的 hash（#）风格。</p><p translation-origin="off">HTML5 style navigation is the router default. In the <a href="guide/router#browser-url-styles">LocationStrategy and browser URL styles</a> Appendix, learn why HTML5 style is preferred, how to adjust its behavior, and how to switch to the older hash (#) style, if necessary.</p></div><p translation-result="on">你必须在应用的 <code>index.html</code> 中<strong>添加一个 <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base" title="base href">&lt;base href&gt; 元素</a></strong>才能让 <code>pushState</code> 路由正常工作。 浏览器要用 <code>&lt;base href&gt;</code> 的值为引用 CSS、脚本和图片文件时使用的<em>相对</em> URL 添加前缀。</p><p translation-origin="off">You must <strong>add a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base" title="base href">&lt;base href&gt; element</a></strong> to the app's <code>index.html</code> for <code>pushState</code> routing to work. The browser uses the <code>&lt;base href&gt;</code> value to prefix <em>relative</em> URLs when referencing CSS files, scripts, and images.</p><p translation-result="on">请把 <code>&lt;base&gt;</code> 元素添加在 <code>&lt;head&gt;</code> 标签的紧后面。如果应用的根目录是 <code>app</code> 目录，那么就可以像这个应用程序一样，设置 <strong><code>index.html</code></strong>中的 <code>href</code> 值。代码如下。</p><p translation-origin="off">Add the <code>&lt;base&gt;</code> element just after the <code>&lt;head&gt;</code> tag. If the <code>app</code> folder is the application root, as it is for this application, set the <code>href</code> value in <strong><code>index.html</code></strong><em>exactly</em> as shown here.</p><code-example path="router/src/index.html" header="src/index.html (base-href)" region="base-href" ng-version="9.0.0-rc.11"><div style="display:none">&lt;base href="/"&gt;</div><header class="ng-star-inserted">src/index.html (base-href)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/index.html (base-href)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;base</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><h4 id="html5-urls-and-the--base-href" translation-result="on">HTML 5 URL 与<em>&lt;base href&gt;</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#html5-urls-and-the--base-href"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="html5-urls-and-the--base-href">HTML5 URLs and the <em>&lt;base href&gt;</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#html5-urls-and-the--base-href"><i class="material-icons">link</i></a></h4><p translation-result="on">由于路由器默认使用“<a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries" target="_blank" title="Browser history push-state">HTML 5 pushState</a>”风格，所以你<em>必须</em>用一个<strong>base href</strong>来配置该策略（Strategy）。</p><p translation-origin="off">While the router uses the <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries" title="Browser history push-state">HTML5 pushState</a> style by default, you <em>must</em> configure that strategy with a <strong>base href</strong>.</p><p translation-result="on">配置该策略的首选方式是往 <code>index.html</code> 的 <code>&lt;head&gt;</code> 中添加一个<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base">&lt;base href&gt; element</a>标签。</p><p translation-origin="off">The preferred way to configure the strategy is to add a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base" title="base href">&lt;base href&gt; element</a> tag in the <code>&lt;head&gt;</code> of the <code>index.html</code>.</p><code-example path="router/src/index.html" header="src/index.html (base-href)" region="base-href" ng-version="9.0.0-rc.11"><div style="display:none">&lt;base href="/"&gt;</div><header class="ng-star-inserted">src/index.html (base-href)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/index.html (base-href)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;base</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">如果没有此标签，当通过“深链接”进入该应用时，浏览器就不能加载资源（图片、CSS、脚本）。如果有人把应用的链接粘贴进浏览器的地址栏或从邮件中点击应用的链接时，这种问题就发生。</p><p translation-origin="off">Without that tag, the browser may not be able to load resources (images, CSS, scripts) when "deep linking" into the app. Bad things could happen when someone pastes an application link into the browser's address bar or clicks such a link in an email.</p><p translation-result="on">有些开发人员可能无法添加 <code>&lt;base&gt;</code> 元素，这可能是因为它们没有访问 <code>&lt;head&gt;</code> 或 <code>index.html</code> 的权限。</p><p translation-origin="off">Some developers may not be able to add the <code>&lt;base&gt;</code> element, perhaps because they don't have access to <code>&lt;head&gt;</code> or the <code>index.html</code>.</p><p translation-result="on">它们仍然可以使用 HTML 5 格式的 URL，但要采取两个步骤进行补救：</p><p translation-origin="off">Those developers may still use HTML5 URLs by taking two remedial steps:</p><ol><li><p translation-result="on">用适当的[APP_BASE_HREF][]值提供（provide）路由器。</p><p translation-origin="off">Provide the router with an appropriate [APP_BASE_HREF][] value.</p></li><li><p translation-result="on">对所有 Web 资源使用<strong>绝对地址</strong>：CSS、图片、脚本、模板 HTML。</p><p translation-origin="off">Use <em>root URLs</em> for all web resources: CSS, images, scripts, and template HTML files.</p></li></ol><a id="hashlocationstrategy"></a><h4 id="hashlocationstrategy" translation-result="on"><em>HashLocationStrategy</em> 策略<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#hashlocationstrategy"><i class="material-icons">link</i></a></h4><h4 translation-origin="off" id="hashlocationstrategy"><em>HashLocationStrategy</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/router#hashlocationstrategy"><i class="material-icons">link</i></a></h4><p translation-result="on">你可以在根模块的 <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> 的第二个参数中传入一个带有 <code>useHash: true</code> 的对象，以回到基于 <code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code> 的传统方式。</p><p translation-origin="off">You can go old-school with the <code><a href="api/common/HashLocationStrategy" class="code-anchor">HashLocationStrategy</a></code> by providing the <code>useHash: true</code> in an object as the second argument of the <code><a href="api/router/RouterModule#forRoot" class="code-anchor">RouterModule.forRoot()</a></code> in the <code>AppModule</code>.</p><code-example path="router/src/app/app.module.6.ts" header="src/app/app.module.ts (hash URL strategy)" ng-version="9.0.0-rc.11"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { <a href="api/router/Routes" class="code-anchor">Routes</a>, <a href="api/router/RouterModule" class="code-anchor">RouterModule</a> } from '@angular/router'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; const routes: <a href="api/router/Routes" class="code-anchor">Routes</a> = [ ]; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ imports: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a>, RouterModule.forRoot(routes, { useHash: true }) // .../#/crisis-center/ ], declarations: [ AppComponent, PageNotFoundComponent ], providers: [ ], bootstrap: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts (hash URL strategy)</header><aio-code class="headed-code"><pre class="lang- prettyprint">      <button title="Copy code snippet" class="material-icons copy-button no-print ng-star-inserted" aria-label="Copy code snippet from src/app/app.module.ts (hash URL strategy)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">             </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">        </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">          </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pun">,</span><span class="pln"> </span><a href="api/router/RouterModule" class="code-anchor"><span class="typ">RouterModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/router'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">          </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">PageNotFoundComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./page-not-found/page-not-found.component'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> routes</span><span class="pun">:</span><span class="pln"> </span><a href="api/router/Routes" class="code-anchor"><span class="typ">Routes</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

</span><span class="pun">];</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span><span class="pln">
  imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span><span class="pln">
    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pun">,</span><span class="pln">
    </span><span class="typ">RouterModule</span><span class="pun">.</span><span class="pln">forRoot</span><span class="pun">(</span><span class="pln">routes</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> useHash</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">})</span><span class="pln">  </span><span class="com">// .../#/crisis-center/</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  declarations</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="typ">AppComponent</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">PageNotFoundComponent</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  providers</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

  </span><span class="pun">],</span><span class="pln">
  bootstrap</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example></div></div></aio-doc-viewer></main></mat-sidenav-content></mat-sidenav-container><div class="toc-container no-print ng-star-inserted"><aio-lazy-ce selector="aio-toc"><aio-toc ng-version="9.0.0-rc.11"><div class="toc-inner no-print collapsed ng-star-inserted"><ul class="toc-list"><li class="h1 ng-star-inserted active" title="路由与导航"><a href="guide/router#routing-and-navigation">路由与导航</a></li><li class="h2 ng-star-inserted" title="概览"><a href="guide/router#overview">概览</a></li><li class="h2 ng-star-inserted" title="基础知识"><a href="guide/router#the-basics">基础知识</a></li><li class="h3 ng-star-inserted" title="<base href> 元素"><a href="guide/router#base-href"><em>&lt;base href&gt;</em> 元素</a></li><li class="h3 ng-star-inserted" title="从路由库中导入"><a href="guide/router#router-imports">从路由库中导入</a></li><li class="h3 ng-star-inserted" title="配置"><a href="guide/router#configuration">配置</a></li><li class="h3 ng-star-inserted" title="路由出口"><a href="guide/router#router-outlet">路由出口</a></li><li class="h3 ng-star-inserted" title="路由器链接"><a href="guide/router#router-links">路由器链接</a></li><li class="h3 ng-star-inserted" title="路由链接的激活状态"><a href="guide/router#active-router-links">路由链接的激活状态</a></li><li class="h3 ng-star-inserted" title="路由器状态"><a href="guide/router#router-state">路由器状态</a></li><li class="h3 ng-star-inserted" title="激活的路由"><a href="guide/router#activated-route">激活的路由</a></li><li class="h3 ng-star-inserted" title="路由事件"><a href="guide/router#router-events">路由事件</a></li><li class="h3 ng-star-inserted" title="总结一下"><a href="guide/router#summary">总结一下</a></li><li class="h2 ng-star-inserted" title="范例应用"><a href="guide/router#the-sample-application">范例应用</a></li><li class="h3 ng-star-inserted" title="范例程序的动图"><a href="guide/router#the-sample-application-in-action">范例程序的动图</a></li><li class="h2 ng-star-inserted" title="里程碑 1：起步"><a href="guide/router#milestone-1-getting-started">里程碑 1：起步</a></li><li class="h3 ng-star-inserted" title="定义路由"><a href="guide/router#define-routes">定义路由</a></li><li class="h3 ng-star-inserted" title="注册路由器与路由定义"><a href="guide/router#register-router-and-routes">注册路由器与路由定义</a></li><li class="h3 ng-star-inserted" title="添加路由出口"><a href="guide/router#add-the-router-outlet">添加路由出口</a></li><li class="h3 ng-star-inserted" title="定义通配符路由"><a href="guide/router#define-a-wildcard-route">定义通配符路由</a></li><li class="h3 ng-star-inserted" title="设置跳转"><a href="guide/router#set-up-redirects">设置跳转</a></li><li class="h3 ng-star-inserted" title="“起步阶段”总结"><a href="guide/router#basics-wrap-up">“起步阶段”总结</a></li><li class="h2 ng-star-inserted" title="里程碑 2：路由模块"><a href="guide/router#milestone-2-routing-module">里程碑 2：<strong>路由模块</strong></a></li><li class="h3 ng-star-inserted" title="把路由集成到应用中"><a href="guide/router#integrate-routing-with-your-app">把路由集成到应用中</a></li><li class="h3 ng-star-inserted" title="将路由配置重构为路由模块"><a href="guide/router#refactor-the-routing-configuration-into-a-routing-module">将路由配置重构为<em>路由模块</em></a></li><li class="h3 ng-star-inserted" title="你需要路由模块吗？"><a href="guide/router#do-you-need-a-routing-module">你需要<strong>路由模块</strong>吗？</a></li><li class="h2 ng-star-inserted" title="里程碑 3: 英雄特征区"><a href="guide/router#milestone-3-heroes-feature">里程碑 3: 英雄特征区</a></li><li class="h3 ng-star-inserted" title="添加英雄管理功能"><a href="guide/router#add-heroes-functionality">添加英雄管理功能</a></li><li class="h3 ng-star-inserted" title="导入模块的顺序很重要"><a href="guide/router#module-import-order-matters">导入模块的顺序很重要</a></li><li class="h3 ng-star-inserted" title="路由参数"><a href="guide/router#route-parameters">路由参数</a></li><li class="h3 ng-star-inserted" title="Activated Route 实战"><a href="guide/router#activated-route-in-action"><em>Activated Route</em> 实战</a></li><li class="h3 ng-star-inserted" title="导航回列表组件"><a href="guide/router#navigating-back-to-the-list-component">导航回列表组件</a></li><li class="h3 ng-star-inserted" title="ActivatedRoute 服务中的路由参数"><a href="guide/router#route-parameters-in-the-activatedroute-service"><em>ActivatedRoute</em> 服务中的路由参数</a></li><li class="h3 ng-star-inserted" title="添加路由动画"><a href="guide/router#adding-routable-animations">添加路由动画</a></li><li class="h3 ng-star-inserted" title="里程碑 3 的总结"><a href="guide/router#milestone-3-wrap-up">里程碑 3 的总结</a></li><li class="h2 ng-star-inserted" title="里程碑 4：危机中心"><a href="guide/router#milestone-4-crisis-center-feature">里程碑 4：危机中心</a></li><li class="h3 ng-star-inserted" title="带有子路由的危机中心"><a href="guide/router#a-crisis-center-with-child-routes">带有子路由的危机中心</a></li><li class="h3 ng-star-inserted" title="子路由组件"><a href="guide/router#child-routing-component">子路由组件</a></li><li class="h3 ng-star-inserted" title="子路由配置"><a href="guide/router#child-route-configuration">子路由配置</a></li><li class="h3 ng-star-inserted" title="把危机中心模块导入到 AppModule 的路由中"><a href="guide/router#import-crisis-center-module-into-the-appmodule-routes">把危机中心模块导入到 <code>AppModule</code> 的路由中</a></li><li class="h3 ng-star-inserted" title="相对导航"><a href="guide/router#relative-navigation">相对导航</a></li><li class="h3 ng-star-inserted" title="使用相对 URL 导航到危机列表"><a href="guide/router#navigate-to-crisis-list-with-a-relative-url">使用相对 URL 导航到危机列表</a></li><li class="h3 ng-star-inserted" title="用命名出口（outlet）显示多重路由"><a href="guide/router#displaying-multiple-routes-in-named-outlets">用命名出口（outlet）显示多重路由</a></li><li class="h2 ng-star-inserted" title="里程碑 5：路由守卫"><a href="guide/router#milestone-5-route-guards">里程碑 5：路由守卫</a></li><li class="h3 ng-star-inserted" title="CanActivate: 要求认证"><a href="guide/router#canactivate-requiring-authentication"><em>CanActivate</em>: 要求认证</a></li><li class="h3 ng-star-inserted" title="CanActivateChild：保护子路由"><a href="guide/router#canactivatechild-guarding-child-routes"><code>CanActivateChild</code>：保护子路由</a></li><li class="h3 ng-star-inserted" title="CanDeactivate：处理未保存的更改"><a href="guide/router#candeactivate-handling-unsaved-changes"><em>CanDeactivate</em>：处理未保存的更改</a></li><li class="h3 ng-star-inserted" title="Resolve: 预先获取组件数据"><a href="guide/router#resolve-pre-fetching-component-data"><em>Resolve</em>: 预先获取组件数据</a></li><li class="h3 ng-star-inserted" title="查询参数及片段"><a href="guide/router#query-parameters-and-fragments">查询参数及片段</a></li><li class="h2 ng-star-inserted" title="里程碑 6：异步路由"><a href="guide/router#milestone-6-asynchronous-routing">里程碑 6：异步路由</a></li><li class="h3 ng-star-inserted" title="惰性加载路由配置"><a href="guide/router#lazy-loading-route-configuration">惰性加载路由配置</a></li><li class="h3 ng-star-inserted" title="CanLoad 守卫：保护对特性模块的未授权加载"><a href="guide/router#canload-guard-guarding-unauthorized-loading-of-feature-modules"><code>CanLoad</code> 守卫：保护对特性模块的未授权加载</a></li><li class="h3 ng-star-inserted" title="预加载：特性区的后台加载"><a href="guide/router#preloading-background-loading-of-feature-areas">预加载：特性区的后台加载</a></li><li class="h3 ng-star-inserted" title="自定义预加载策略"><a href="guide/router#custom-preloading-strategy">自定义预加载策略</a></li><li class="h2 ng-star-inserted" title="使用重定向迁移 URL"><a href="guide/router#migrating-urls-with-redirects">使用重定向迁移 URL</a></li><li class="h3 ng-star-inserted" title="把 /heroes 修改为 /superheros"><a href="guide/router#changing-heroes-to-superheroes">把 <code>/heroes</code> 修改为 <code>/superheros</code></a></li><li class="h2 ng-star-inserted" title="审查路由器配置"><a href="guide/router#inspect-the-routers-configuration">审查路由器配置</a></li><li class="h2 ng-star-inserted" title="总结与最终的应用"><a href="guide/router#wrap-up-and-final-app">总结与最终的应用</a></li><li class="h2 ng-star-inserted" title="附录"><a href="guide/router#appendices">附录</a></li><li class="h3 ng-star-inserted" title="附录：链接参数数组"><a href="guide/router#appendix-link-parameters-array">附录：链接参数数组</a></li><li class="h3 ng-star-inserted" title="附录：LocationStrategy 以及浏览器 URL 样式"><a href="guide/router#appendix-locationstrategy-and-browser-url-styles">附录：<em>LocationStrategy</em> 以及浏览器 URL 样式</a></li></ul></div></aio-toc></aio-lazy-ce></div><footer class="no-print"><aio-footer><div class="grid-fluid"><div class="footer-block ng-star-inserted"><h3>资源</h3><ul><li class="ng-star-inserted"><a class="link" href="about" title="Angular 贡献者。">关于</a></li><li class="ng-star-inserted"><a class="link" href="resources" title="网络上的 Angular 工具、培训、博客等">资源列表</a></li><li class="ng-star-inserted"><a class="link" href="presskit" title="我们的联系方式、LOGO 和品牌">宣传资料</a></li><li class="ng-star-inserted"><a class="link" href="https://blog.angular.io/" title="Angular 官方博客">博客</a></li><li class="ng-star-inserted"><a class="link" href="analytics" title="Angular 使用情况分析">使用情况分析</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>帮助</h3><ul><li class="ng-star-inserted"><a class="link" href="https://stackoverflow.com/questions/tagged/angular" title="Stack Overflow: 这里的社区会回答你关于 Angular 的技术问题">Stack Overflow</a></li><li class="ng-star-inserted"><a class="link" href="https://gitter.im/angular/angular" title="和老鸟聊 Angular">Gitter</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/angular/issues" title="在 github 上报告问题和建议。">报告问题</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md" title="让我们彼此尊重">行为规范</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>社区</h3><ul><li class="ng-star-inserted"><a class="link" href="events" title="Angular events around the world.">活动</a></li><li class="ng-star-inserted"><a class="link" href="http://www.meetup.com/topics/angularjs/" title="参加聚会，向别的开发人员学习">聚会</a></li><li class="ng-star-inserted"><a class="link" href="https://twitter.com/angular" title="Twitter">Twitter</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/angular" title="GitHub">GitHub</a></li><li class="ng-star-inserted"><a class="link" href="contribute" title="向 Angular 做贡献">做贡献</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>多语言</h3><ul><li class="ng-star-inserted"><a class="link" href="https://angular.io/" title="English Version.">English Version</a></li><li class="ng-star-inserted"><a class="link" href="https://angular.tw/" title="正體中文版">正體中文版</a></li><li class="ng-star-inserted"><a class="link" href="https://angular.jp/" title="日本語版">日本語版</a></li><li class="ng-star-inserted"><a class="link" href="https://angular.kr/" title="한국어">한국어</a></li></ul></div></div><p>Super-powered by Google ©2010-2020. 代码授权方式：<a href="license" title="License text">MIT-style License</a>. 文档授权方式：<a href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.</p><p>当前版本：9.0.1-build.109+sha.7a49faba.</p></aio-footer></footer><div class="cdk-visually-hidden ng-star-inserted"><mat-icon role="img" class="mat-icon notranslate material-icons mat-icon-no-color" aria-hidden="true">&nbsp;</mat-icon></div></aio-shell><noscript><div class="background-sky hero"></div><section id="intro" style="text-shadow:1px 1px #1976d2"><div class="hero-logo"><img src="assets/images/logos/angular/angular.svg" width="250" height="250" alt="Angular"></div><div class="homepage-container"><div class="hero-headline">一套框架，多种平台<br>移动 &amp; 桌面</div></div></section><h2 style="color:red;margin-top:40px;position:relative;text-align:center;text-shadow:1px 1px #fafafa"><b><i>该网站需要浏览器支持 JavaScript</i></b></h2></noscript><script src="runtime-es2015.811b066977719df5af39.js" type="module"></script><script src="runtime-es5.811b066977719df5af39.js" nomodule="" defer=""></script><script src="polyfills-es5.1494ca908613f3429457.js" nomodule="" defer=""></script><script src="polyfills-es2015.9057a05c650bf60ecbf4.js" type="module"></script><script src="main-es2015.4e9aa34b562bab1382ab.js" type="module"></script><script src="main-es5.4e9aa34b562bab1382ab.js" nomodule="" defer=""></script><div class="cdk-live-announcer-element cdk-visually-hidden" aria-atomic="true" aria-live="polite"></div></body></html>